From fc4a4a51015b886e608cdc5526052bc6a1bfc7a4 Mon Sep 17 00:00:00 2001 From: Harish Kumar Date: Mon, 19 Oct 2026 13:37:15 +0530 Subject: [PATCH 1/4] fix: resolve CLI as altimate or altimate-code `altimate` is the CLI's canonical name since v0.7.1. The npm package exposes both `altimate` and `altimate-code`, but the curl, Homebrew and PowerShell installers expose only `altimate`, so the plugin reported the CLI as missing on standalone installs. Every CLI invocation in the skills and slash commands now resolves the binary in the same shell call, trying `altimate` first and falling back to `altimate-code`, ignoring aliases and shell functions. It exits 127 with a clear message before mktemp when neither is installed, which replaces the separate `command -v` pre-check. Install guidance lists both the npm and curl installs. Adds tests/resolve-cli.sh, which checks every resolver copy is identical and resolves correctly in bash and zsh. Bumps the plugin to 1.1.0. Co-Authored-By: Claude Opus 5.5 --- CONTRIBUTING.md | 2 + README.md | 7 +- .../altimate-code/.codex-plugin/plugin.json | 2 +- plugins/altimate-code/CHANGELOG.md | 6 ++ plugins/altimate-code/README.md | 17 +++-- plugins/altimate-code/commands/altimate.md | 22 +++--- plugins/altimate-code/commands/review.md | 24 +++++-- .../skills/altimate-code/SKILL.md | 26 ++++--- plugins/altimate-code/skills/review/SKILL.md | 24 +++++-- tests/resolve-cli.sh | 71 +++++++++++++++++++ 10 files changed, 159 insertions(+), 42 deletions(-) create mode 100755 tests/resolve-cli.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06887f0..0751b91 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,6 +73,8 @@ description: >- ## Testing changes +If you touch the CLI resolver block in a skill or command, run `./tests/resolve-cli.sh` — it checks every copy is identical and resolves correctly in bash and zsh. + Smoke-install the plugin from your working copy: ```bash diff --git a/README.md b/README.md index 867f047..cebd0f4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Codex plugin that delegates dbt and warehouse work to [`altimate-code`](https:// One skill: **`altimate-code`** — routes tasks that touch live warehouse state, column lineage, cross-database work, query-cost attribution, schema diffs, PII detection, or FinOps reporting to the altimate-code subprocess. The skill body encodes: -- how to check that `altimate-code` is installed +- how to resolve the CLI (`altimate` or `altimate-code`) and detect that it is not installed - which agent persona (`fast-edit` / `analyst` / `builder`) to pick for the task shape - the exact non-interactive invocation with `--yolo` / `--output` / `--dir` - when to add `--continue` for follow-up tasks in a warm session @@ -68,10 +68,11 @@ altimate-codex-plugin/ The delegation skill spawns `altimate-code` as a subprocess. Install the companion CLI: ```bash -npm install -g altimate-code +npm install -g altimate-code # Node 20+; exposes `altimate-code` and `altimate` +curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes only `altimate` ``` -Node 20+. After install, run `altimate-code` once to configure your LLM provider auth and warehouse connections through the TUI. +After install, run `altimate` once to configure your LLM provider auth and warehouse connections through the TUI. ## License & legal diff --git a/plugins/altimate-code/.codex-plugin/plugin.json b/plugins/altimate-code/.codex-plugin/plugin.json index 2d9c7b6..071291e 100644 --- a/plugins/altimate-code/.codex-plugin/plugin.json +++ b/plugins/altimate-code/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "altimate-code", - "version": "1.0.0", + "version": "1.1.0", "description": "Delegates dbt and warehouse work to altimate-code, a specialized CLI agent with 100+ purpose-built data tools (SQL analysis, column-level lineage, dbt build/test/run, warehouse profiling, FinOps, connectivity to Snowflake, BigQuery, Redshift, Databricks, Postgres, MySQL, DuckDB).", "author": { "name": "Altimate AI", diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index b72a849..0c0147e 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to the Altimate Code Codex plugin are recorded here. 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). +## [1.1.0] — 2026-10-19 + +### Fixed +- The skills and slash commands now resolve the CLI as `altimate`, its canonical name since v0.7.1, and fall back to `altimate-code` for older npm installs. Standalone installs (curl, Homebrew, PowerShell) expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. +- Install guidance and recovery messages now list both the npm and curl install methods and point to `altimate` for first-run auth setup. + ## [1.0.0] — 2026-07-18 ### Added diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 871441c..e507bad 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -18,13 +18,16 @@ Adding the marketplace makes the plugin discoverable in the `/plugins` browser b ## Prerequisites -The altimate-code CLI must be installed and configured on your PATH: +The altimate-code CLI must be installed and configured on your PATH. Either install method works: ```bash -npm install -g altimate-code # requires Node 20+ -altimate-code # launch the TUI, then run /connect to configure your LLM provider +npm install -g altimate-code # requires Node 20+; exposes `altimate-code` and `altimate` +curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes only `altimate` +altimate # launch the TUI, then run /connect to configure your LLM provider ``` +The plugin invokes `altimate`, the CLI's canonical name, and falls back to `altimate-code` for npm installs older than v0.7.1, so standalone installs work without an `altimate-code` alias. + Or configure a provider via environment variable (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and 20+ others — see the [altimate-code docs](https://docs.altimate.sh)). If altimate-code is not on PATH or not configured, the plugin surfaces the failure with fix instructions rather than silently falling back to Codex's native tools. @@ -57,12 +60,12 @@ Full details: **[PRIVACY.md](../../PRIVACY.md)** · Security policy and disclosu | Symptom | Fix | |---|---| -| `command not found: altimate-code` | `npm install -g altimate-code` (Node 20+), then run `altimate-code` once to configure your provider. | -| `Unauthorized` / `No provider configured` | Run `altimate-code` to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | +| `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider. | +| `Unauthorized` / `No provider configured` | Run `altimate` to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | | `Error: Unexpected error — Unknown: FileSystem.open (…altimate-code/log/opencode.log)` | Codex's default `workspace-write` sandbox blocks writes to `~/.local/share/altimate-code/log/`, where the CLI writes its log. Re-run with `codex exec --sandbox danger-full-access …`, or pass `-c 'sandbox_permissions=["disk-full-write-access"]'` on the specific invocation. Frequent users can raise the default in `~/.codex/config.toml`. Codex has no per-plugin sandbox-permission declaration in its manifest schema today, so this is a per-invocation flag. | -| Task hangs for several minutes | Open `altimate-code` to check for a pending prompt in the TUI, or re-run specifying a known-good model. | +| Task hangs for several minutes | Open `altimate` to check for a pending prompt in the TUI, or re-run specifying a known-good model. | | Empty result | The task may be too ambiguous — restate with the target table, expected columns, or time window. | -| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate-code` TUI or `profiles.yml`. | +| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate` TUI or `profiles.yml`. | | Plugin installed but never delegates | Confirm the SessionStart hook is trusted — Codex asks on first use; if you skipped it, uninstall and reinstall from `/plugins`. | | Plugin doesn't appear in `/plugins` | Confirm the marketplace is registered: `codex plugin marketplace add AltimateAI/altimate-codex-plugin`, then re-open `/plugins`. | diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index 5c60f3b..3829f93 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -3,16 +3,12 @@ description: Delegate a task to altimate-code, the specialised data-engineering argument-hint: --- -The user explicitly invoked `/altimate-code:altimate` to delegate this task to altimate-code. You MUST run the task via the `altimate-code` CLI — do NOT attempt the work with native `Bash`/`Edit`/`Write` tools. +The user explicitly invoked `/altimate-code:altimate` to delegate this task to altimate-code. You MUST run the task via the altimate-code CLI — do NOT attempt the work with native `Bash`/`Edit`/`Write` tools. Workflow (follow in order, no skipping): -1. **Verify altimate-code is installed:** - ```bash - command -v altimate-code - ``` - If it returns nothing, stop and tell the user: - > altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+), then run `altimate-code` once to configure your provider/warehouse auth, then re-run `/altimate-code:altimate `. +1. **Verify altimate-code is installed.** There is no separate check: the run command in step 3 resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Either one is fine. If the run exits with `altimate-code CLI not found`, stop and tell the user: + > altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install | bash`, then run `altimate` once to configure your provider/warehouse auth, then re-run `/altimate-code:altimate `. 2. **Pick the agent persona** based on the user's task shape. Start cheap and escalate on failure — fast-edit handles most dbt/SQL work at 10–20× lower cost than builder. @@ -35,9 +31,13 @@ Workflow (follow in order, no skipping): $ARGUMENTS ALTIMATE_TASK )" + for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + done + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" - altimate-code run "$TASK" \ + "$ALTIMATE_BIN" run "$TASK" \ --agent \ --yolo \ --output "$OUTPUT_FILE" \ @@ -51,9 +51,13 @@ Workflow (follow in order, no skipping): $ARGUMENTS ALTIMATE_TASK )" + for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + done + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" - altimate-code run "$TASK" \ + "$ALTIMATE_BIN" run "$TASK" \ --agent \ --yolo --output "$OUTPUT_FILE" --dir "$(pwd)" \ --continue diff --git a/plugins/altimate-code/commands/review.md b/plugins/altimate-code/commands/review.md index b70a6f8..d9045e5 100644 --- a/plugins/altimate-code/commands/review.md +++ b/plugins/altimate-code/commands/review.md @@ -16,15 +16,25 @@ Run the `altimate-code review` CLI on the current dbt project and present the si ## Workflow -1. **Verify altimate-code is on PATH.** Run `command -v altimate-code`. If nothing is returned, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+), then run 'altimate-code' once to configure your provider and warehouse auth."` — then STOP. +1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same Bash call as the review. If it exits 127 with `altimate-code CLI not found`, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+) or 'curl -fsSL https://www.altimate.sh/install | bash', then run 'altimate' once to configure your provider and warehouse auth."` — then STOP. + + The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same Bash call as this resolver (shell state does not persist between calls). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + + ```bash + for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + done + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + "$ALTIMATE_BIN" review # plus any scope/flags from below + ``` 2. **Confirm you are in a dbt project root** (`dbt_project.yml` present). If not, tell the user to `cd` there and STOP. 3. **Determine scope from `$ARGUMENTS`:** - - Empty → `altimate-code review` - - Commit SHA (matches `[0-9a-f]{7,40}`) → `altimate-code review --base $ARGUMENTS~1 --head $ARGUMENTS` - - Branch name (matches local branch via `git rev-parse`) → `altimate-code review --base $ARGUMENTS` - - PR URL or number → first `gh pr checkout `, then `altimate-code review` + - Empty → `"$ALTIMATE_BIN" review` + - Commit SHA (matches `[0-9a-f]{7,40}`) → `"$ALTIMATE_BIN" review --base $ARGUMENTS~1 --head $ARGUMENTS` + - Branch name (matches local branch via `git rev-parse`) → `"$ALTIMATE_BIN" review --base $ARGUMENTS` + - PR URL or number → first `gh pr checkout `, then `"$ALTIMATE_BIN" review` 4. **Run the review command as chosen above.** Capture its stdout. @@ -53,8 +63,8 @@ Anything else (`--manifest`, `--cwd`) only if the user explicitly requested it o | Symptom | Message to user | |---|---| -| `command not found: altimate-code` | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+), then run `altimate-code` once to configure auth." | -| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` to reconfigure, or re-run with `--no-ai`." | +| `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth." | +| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` to reconfigure, or re-run with `--no-ai`." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` needs git to compute the diff." | | No `dbt_project.yml` | "No dbt project detected at this path. Run from the directory with `dbt_project.yml`." | | Output mentions `DEGRADED — lint-only` | Present verbatim; do NOT silently upgrade a degraded run to a full verdict. | diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 7a52155..c951694 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -21,7 +21,7 @@ altimate-code is a CLI AI agent with 100+ purpose-built data engineering tools. ## You MUST follow this workflow -1. **Verify altimate-code is on PATH** with `command -v altimate-code`. If it returns nothing, jump to "Not installed" below and stop. +1. **Verify altimate-code is on PATH.** There is no separate check: the invocation below resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Either name is the same CLI. If the invocation exits with `altimate-code CLI not found`, jump to "Failure modes" below and stop. 2. **Run altimate-code with the user's task** using the invocation below. Pass the user's request through verbatim — do not paraphrase or split it. 3. **Read the output file** and present it to the user as-is. @@ -55,9 +55,13 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" +for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break +done +[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" -altimate-code run "$TASK" \ +"$ALTIMATE_BIN" run "$TASK" \ --agent \ --yolo \ --output "$OUTPUT_FILE" \ @@ -75,6 +79,8 @@ Then `Read "$OUTPUT_FILE"` and emit its contents to the user without re-summaris | `--output "$OUTPUT_FILE"` | Captures the final response. Use the private `mktemp` file from above — do NOT use a fixed path like `/tmp/altimate-result.md`; concurrent sessions clobber each other and a world-readable fixed path leaks data. | | `--dir "$(pwd)"` | Runs altimate-code in the current project so it picks up dbt project config, profiles.yml, etc. | +Each Bash call starts a fresh shell, so keep the `ALTIMATE_BIN` resolver loop inside the same command as the `run` — do not resolve it in an earlier call and reuse the variable. + ### Follow-up tasks in the same project When the user makes a follow-up data task in the same project after a successful altimate-code delegation, prefer `--continue` to resume the warm session instead of starting a fresh one. Same here-doc + `mktemp` pattern: @@ -84,9 +90,13 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" +for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break +done +[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" -altimate-code run "$TASK" \ +"$ALTIMATE_BIN" run "$TASK" \ --agent \ --yolo \ --output "$OUTPUT_FILE" \ @@ -104,16 +114,16 @@ When altimate-code returns an error, **report the error to the user and STOP**. | Symptom | What to tell the user — verbatim | |---|---| -| `command not found: altimate-code` | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) and run `altimate-code` once to configure auth. Then re-run your request." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` in your terminal to open the TUI and reconfigure your provider, then re-run your request." | -| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate-code` to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | +| `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth. Then re-run your request." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` in your terminal to open the TUI and reconfigure your provider, then re-run your request." | +| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate` to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | | Output file empty | "altimate-code returned without producing output. The task may be too ambiguous — please restate with more detail (target table, expected columns, time window)." | -| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via `altimate-code` TUI." | +| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via the `altimate` TUI." | In every row, the instruction to the user is the action — you do not retry the task with native tools. If the user fixes the underlying issue and asks again, you delegate again. ## Notes - altimate-code runs its own LLM, separate from the host agent's. Costs and rate limits accrue to altimate-code's configured provider. -- Sessions persist in altimate-code's local store — `altimate-code session list` shows prior runs; `--continue` resumes the latest, `--session ` resumes a specific one. +- Sessions persist in altimate-code's local store — `altimate-code session list` (or `altimate session list`) shows prior runs; `--continue` resumes the latest, `--session ` resumes a specific one. - For very long tasks, the `--output` file is the source of truth — stdout buffering can drop content. diff --git a/plugins/altimate-code/skills/review/SKILL.md b/plugins/altimate-code/skills/review/SKILL.md index 8f838dc..5cb32ce 100644 --- a/plugins/altimate-code/skills/review/SKILL.md +++ b/plugins/altimate-code/skills/review/SKILL.md @@ -27,7 +27,17 @@ description: >- ## You MUST follow this workflow -1. **Verify altimate-code is on PATH** with `command -v altimate-code`. If it returns nothing, jump to "Failure modes" below and stop. +1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same Bash call as the review. If it exits 127 with `altimate-code CLI not found`, jump to "Failure modes" below and stop. + + The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same Bash call as this resolver (shell state does not persist between calls). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + + ```bash + for ALTIMATE_NAME in altimate altimate-code; do + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + done + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + "$ALTIMATE_BIN" review # plus any scope/flags from below + ``` 2. **Determine review scope from the user's ask** using the table below. @@ -41,10 +51,10 @@ description: >- | User says | Command to run | |---|---| -| "review my changes" / "review this branch" / "audit my dbt work" / no scope specified | `altimate-code review` (default: working tree vs merge-base with `origin/main`) | -| "review PR #123" or gives a GitHub PR URL | First `gh pr checkout 123`, then `altimate-code review` | -| "review commit `abc123`" | `altimate-code review --base abc123~1 --head abc123` | -| "compare staging to prod" / "review the diff between two branches" | `altimate-code review --base prod --head staging` | +| "review my changes" / "review this branch" / "audit my dbt work" / no scope specified | `"$ALTIMATE_BIN" review` (default: working tree vs merge-base with `origin/main`) | +| "review PR #123" or gives a GitHub PR URL | First `gh pr checkout 123`, then `"$ALTIMATE_BIN" review` | +| "review commit `abc123`" | `"$ALTIMATE_BIN" review --base abc123~1 --head abc123` | +| "compare staging to prod" / "review the diff between two branches" | `"$ALTIMATE_BIN" review --base prod --head staging` | ## Do NOT do these @@ -68,8 +78,8 @@ description: >- | Symptom | Message to the user | |---|---| -| `command not found: altimate-code` | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+), then run `altimate-code` once to configure your provider and warehouse auth. Then re-run the review." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | +| `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider and warehouse auth. Then re-run the review." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` computes the diff via git — run from a dbt project inside a git worktree." | | No `dbt_project.yml` found | "No dbt project detected at this path. The review needs a dbt project to compile models against. Run from the directory containing `dbt_project.yml`." | | Output says `DEGRADED — lint-only` | Present that note verbatim. Do not silently upgrade a degraded run to a full verdict. | diff --git a/tests/resolve-cli.sh b/tests/resolve-cli.sh new file mode 100755 index 0000000..70a9411 --- /dev/null +++ b/tests/resolve-cli.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# Checks the CLI resolver block embedded in the skills and slash commands: +# every copy must be identical, and it must pick the right binary in bash and zsh. +set -u +cd "$(dirname "$0")/.." + +# file:expected number of resolver blocks +FILES=( + plugins/altimate-code/commands/altimate.md:2 + plugins/altimate-code/commands/review.md:1 + plugins/altimate-code/skills/altimate-code/SKILL.md:2 + plugins/altimate-code/skills/review/SKILL.md:1 +) +FAILURES=0 +fail() { echo "FAIL: $*"; FAILURES=$((FAILURES + 1)); } + +# Print each resolver block (loop start through the not-found guard) on one line, dedented. +extract_blocks() { + awk '/for ALTIMATE_NAME in/ {grab=1; block=""} + grab {sub(/^ */, ""); block = block $0 "\\n"} + grab && /CLI not found/ {grab=0; print block}' "$1" +} + +ALL_BLOCKS="" +for entry in "${FILES[@]}"; do + file="${entry%:*}" + blocks="$(extract_blocks "$file")" + count="$(printf '%s' "$blocks" | grep -c .)" + [ "$count" -eq "${entry##*:}" ] || fail "$file has $count resolver blocks, expected ${entry##*:}" + ALL_BLOCKS="$ALL_BLOCKS$blocks"$'\n' +done +[ "$(printf '%s' "$ALL_BLOCKS" | grep . | sort -u | grep -c .)" -eq 1 ] || fail "resolver blocks differ between files" +RESOLVER="$(printf '%b' "$(printf '%s' "$ALL_BLOCKS" | head -n1)")" + +STUBS="$(mktemp -d)" +trap 'rm -rf "$STUBS"' EXIT +for stub in only-altimate/altimate only-altimate-code/altimate-code both/altimate both/altimate-code "relative dir/altimate"; do + mkdir -p "$STUBS/$(dirname "$stub")" + printf '#!/bin/sh\necho "ran %s"\n' "$(basename "$stub")" > "$STUBS/$stub" + chmod +x "$STUBS/$stub" +done +mkdir -p "$STUBS/neither" + +# expect +# Runs from $STUBS without startup files, so relative PATH entries resolve and user config can't interfere. +expect() { + local shell_cmd + case "$1" in zsh) shell_cmd=(zsh -f) ;; *) shell_cmd=(bash --noprofile --norc) ;; esac + out="$(cd "$STUBS" && env -u BASH_ENV -u ENV PATH="$2:/usr/bin:/bin" "${shell_cmd[@]}" -c "$3 +$RESOLVER +\"\$ALTIMATE_BIN\"" 2>&1)" + status=$? + [ "$status" -eq "$4" ] && [ "$out" = "$5" ] \ + || fail "$1 / PATH=$2 / '${3:-no setup}': expected exit $4 '$5', got exit $status '$out'" +} + +ALIAS_SETUP='shopt -s expand_aliases 2>/dev/null; alias altimate-code=altimate' +for sh in bash zsh; do + command -v "$sh" >/dev/null || { echo "skip: $sh not installed"; continue; } + expect "$sh" "$STUBS/only-altimate" '' 0 'ran altimate' + expect "$sh" "$STUBS/only-altimate-code" '' 0 'ran altimate-code' + expect "$sh" "$STUBS/both" '' 0 'ran altimate' + expect "$sh" "$STUBS/neither" '' 127 'altimate-code CLI not found (tried altimate, altimate-code)' + expect "$sh" "$STUBS/only-altimate" "$ALIAS_SETUP" 0 'ran altimate' + expect "$sh" "$STUBS/only-altimate" "$ALIAS_SETUP; altimate() { echo function; }" 0 'ran altimate' + expect "$sh" "$STUBS/only-altimate" 'altimate-code() { echo function; }' 0 'ran altimate' + expect "$sh" "$STUBS/only-altimate-code" 'shopt -s expand_aliases 2>/dev/null; alias altimate=altimate-code' 0 'ran altimate-code' + expect "$sh" "relative dir" '' 0 'ran altimate' +done + +[ "$FAILURES" -eq 0 ] && echo "ok" || { echo "$FAILURES failure(s)"; exit 1; } From c941ad4644e6650030ee9a90a479e64cd155cd87 Mon Sep 17 00:00:00 2001 From: Harish Kumar Date: Mon, 19 Oct 2026 13:54:02 +0530 Subject: [PATCH 2/4] fix: check the CLI before gh pr checkout and require an executable The review flow ran `gh pr checkout` before resolving the CLI, so a machine without it had its branch switched before "not found" was reported. The PR-scope command now runs after the resolver in the same shell command. bash's `command -v` returns a non-executable file when no executable match exists, so a broken `altimate` on PATH beat a working `altimate-code`. The resolver now only accepts an executable path. Recovery messages name `altimate-code` for npm installs older than v0.7.1, which the resolver still supports. Instructions say "shell command" rather than "Bash call", since Codex runs a generic shell. The resolver test checks its temp dir, runs with only the stub dirs on PATH, and covers legacy-only installs with an alias or function, aliases and functions with nothing installed, and a non-executable `altimate` with and without a legacy fallback. Co-Authored-By: Claude Opus 5.5 (1M context) --- plugins/altimate-code/CHANGELOG.md | 1 + plugins/altimate-code/README.md | 6 +++--- plugins/altimate-code/commands/altimate.md | 6 ++++-- plugins/altimate-code/commands/review.md | 11 ++++++----- .../altimate-code/skills/altimate-code/SKILL.md | 14 ++++++++------ plugins/altimate-code/skills/review/SKILL.md | 11 ++++++----- tests/resolve-cli.sh | 17 ++++++++++++----- 7 files changed, 40 insertions(+), 26 deletions(-) diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 0c0147e..43d3bfc 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Fixed - The skills and slash commands now resolve the CLI as `altimate`, its canonical name since v0.7.1, and fall back to `altimate-code` for older npm installs. Standalone installs (curl, Homebrew, PowerShell) expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. - Install guidance and recovery messages now list both the npm and curl install methods and point to `altimate` for first-run auth setup. +- The CLI lookup ignores aliases and shell functions, skips a non-executable `altimate` in favour of a working `altimate-code`, and runs before `gh pr checkout` in PR reviews, so a missing CLI never switches your branch. Recovery messages name `altimate-code` for npm installs older than v0.7.1. ## [1.0.0] — 2026-07-18 diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index e507bad..0970cbe 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -61,11 +61,11 @@ Full details: **[PRIVACY.md](../../PRIVACY.md)** · Security policy and disclosu | Symptom | Fix | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider. | -| `Unauthorized` / `No provider configured` | Run `altimate` to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | +| `Unauthorized` / `No provider configured` | Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | | `Error: Unexpected error — Unknown: FileSystem.open (…altimate-code/log/opencode.log)` | Codex's default `workspace-write` sandbox blocks writes to `~/.local/share/altimate-code/log/`, where the CLI writes its log. Re-run with `codex exec --sandbox danger-full-access …`, or pass `-c 'sandbox_permissions=["disk-full-write-access"]'` on the specific invocation. Frequent users can raise the default in `~/.codex/config.toml`. Codex has no per-plugin sandbox-permission declaration in its manifest schema today, so this is a per-invocation flag. | -| Task hangs for several minutes | Open `altimate` to check for a pending prompt in the TUI, or re-run specifying a known-good model. | +| Task hangs for several minutes | Open `altimate` (`altimate-code` on npm installs older than v0.7.1) to check for a pending prompt in the TUI, or re-run specifying a known-good model. | | Empty result | The task may be too ambiguous — restate with the target table, expected columns, or time window. | -| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate` TUI or `profiles.yml`. | +| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate` TUI (`altimate-code` on npm installs older than v0.7.1) or `profiles.yml`. | | Plugin installed but never delegates | Confirm the SessionStart hook is trusted — Codex asks on first use; if you skipped it, uninstall and reinstall from `/plugins`. | | Plugin doesn't appear in `/plugins` | Confirm the marketplace is registered: `codex plugin marketplace add AltimateAI/altimate-codex-plugin`, then re-open `/plugins`. | diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index 3829f93..525d7e1 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -32,7 +32,8 @@ Workflow (follow in order, no skipping): ALTIMATE_TASK )" for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 @@ -52,7 +53,8 @@ Workflow (follow in order, no skipping): ALTIMATE_TASK )" for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 diff --git a/plugins/altimate-code/commands/review.md b/plugins/altimate-code/commands/review.md index d9045e5..aee62fd 100644 --- a/plugins/altimate-code/commands/review.md +++ b/plugins/altimate-code/commands/review.md @@ -16,13 +16,14 @@ Run the `altimate-code review` CLI on the current dbt project and present the si ## Workflow -1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same Bash call as the review. If it exits 127 with `altimate-code CLI not found`, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+) or 'curl -fsSL https://www.altimate.sh/install | bash', then run 'altimate' once to configure your provider and warehouse auth."` — then STOP. +1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+) or 'curl -fsSL https://www.altimate.sh/install | bash', then run 'altimate' once to configure your provider and warehouse auth."` — then STOP. - The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same Bash call as this resolver (shell state does not persist between calls). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } "$ALTIMATE_BIN" review # plus any scope/flags from below @@ -34,7 +35,7 @@ Run the `altimate-code review` CLI on the current dbt project and present the si - Empty → `"$ALTIMATE_BIN" review` - Commit SHA (matches `[0-9a-f]{7,40}`) → `"$ALTIMATE_BIN" review --base $ARGUMENTS~1 --head $ARGUMENTS` - Branch name (matches local branch via `git rev-parse`) → `"$ALTIMATE_BIN" review --base $ARGUMENTS` - - PR URL or number → first `gh pr checkout `, then `"$ALTIMATE_BIN" review` + - PR URL or number → `gh pr checkout && "$ALTIMATE_BIN" review`, in the same shell command after the resolver so a missing CLI stops before the checkout 4. **Run the review command as chosen above.** Capture its stdout. @@ -64,7 +65,7 @@ Anything else (`--manifest`, `--cwd`) only if the user explicitly requested it o | Symptom | Message to user | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth." | -| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` to reconfigure, or re-run with `--no-ai`." | +| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to reconfigure, or re-run with `--no-ai`." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` needs git to compute the diff." | | No `dbt_project.yml` | "No dbt project detected at this path. Run from the directory with `dbt_project.yml`." | | Output mentions `DEGRADED — lint-only` | Present verbatim; do NOT silently upgrade a degraded run to a full verdict. | diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index c951694..cb632b2 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -56,7 +56,8 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 @@ -79,7 +80,7 @@ Then `Read "$OUTPUT_FILE"` and emit its contents to the user without re-summaris | `--output "$OUTPUT_FILE"` | Captures the final response. Use the private `mktemp` file from above — do NOT use a fixed path like `/tmp/altimate-result.md`; concurrent sessions clobber each other and a world-readable fixed path leaks data. | | `--dir "$(pwd)"` | Runs altimate-code in the current project so it picks up dbt project config, profiles.yml, etc. | -Each Bash call starts a fresh shell, so keep the `ALTIMATE_BIN` resolver loop inside the same command as the `run` — do not resolve it in an earlier call and reuse the variable. +Each shell command starts a fresh shell, so keep the `ALTIMATE_BIN` resolver loop inside the same command as the `run` — do not resolve it in an earlier call and reuse the variable. ### Follow-up tasks in the same project @@ -91,7 +92,8 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } umask 077 @@ -115,10 +117,10 @@ When altimate-code returns an error, **report the error to the user and STOP**. | Symptom | What to tell the user — verbatim | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth. Then re-run your request." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` in your terminal to open the TUI and reconfigure your provider, then re-run your request." | -| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate` to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) in your terminal to open the TUI and reconfigure your provider, then re-run your request." | +| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate` (`altimate-code` on npm installs older than v0.7.1) to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | | Output file empty | "altimate-code returned without producing output. The task may be too ambiguous — please restate with more detail (target table, expected columns, time window)." | -| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via the `altimate` TUI." | +| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via the `altimate` TUI (`altimate-code` on npm installs older than v0.7.1)." | In every row, the instruction to the user is the action — you do not retry the task with native tools. If the user fixes the underlying issue and asks again, you delegate again. diff --git a/plugins/altimate-code/skills/review/SKILL.md b/plugins/altimate-code/skills/review/SKILL.md index 5cb32ce..a157d4e 100644 --- a/plugins/altimate-code/skills/review/SKILL.md +++ b/plugins/altimate-code/skills/review/SKILL.md @@ -27,13 +27,14 @@ description: >- ## You MUST follow this workflow -1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same Bash call as the review. If it exits 127 with `altimate-code CLI not found`, jump to "Failure modes" below and stop. +1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, jump to "Failure modes" below and stop. - The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same Bash call as this resolver (shell state does not persist between calls). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash for ALTIMATE_NAME in altimate altimate-code; do - ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" && break + ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" + [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } "$ALTIMATE_BIN" review # plus any scope/flags from below @@ -52,7 +53,7 @@ description: >- | User says | Command to run | |---|---| | "review my changes" / "review this branch" / "audit my dbt work" / no scope specified | `"$ALTIMATE_BIN" review` (default: working tree vs merge-base with `origin/main`) | -| "review PR #123" or gives a GitHub PR URL | First `gh pr checkout 123`, then `"$ALTIMATE_BIN" review` | +| "review PR #123" or gives a GitHub PR URL | `gh pr checkout 123 && "$ALTIMATE_BIN" review`, in the same shell command after the resolver so a missing CLI stops before the checkout | | "review commit `abc123`" | `"$ALTIMATE_BIN" review --base abc123~1 --head abc123` | | "compare staging to prod" / "review the diff between two branches" | `"$ALTIMATE_BIN" review --base prod --head staging` | @@ -79,7 +80,7 @@ description: >- | Symptom | Message to the user | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider and warehouse auth. Then re-run the review." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` computes the diff via git — run from a dbt project inside a git worktree." | | No `dbt_project.yml` found | "No dbt project detected at this path. The review needs a dbt project to compile models against. Run from the directory containing `dbt_project.yml`." | | Output says `DEGRADED — lint-only` | Present that note verbatim. Do not silently upgrade a degraded run to a full verdict. | diff --git a/tests/resolve-cli.sh b/tests/resolve-cli.sh index 70a9411..c1b2950 100755 --- a/tests/resolve-cli.sh +++ b/tests/resolve-cli.sh @@ -32,21 +32,23 @@ done [ "$(printf '%s' "$ALL_BLOCKS" | grep . | sort -u | grep -c .)" -eq 1 ] || fail "resolver blocks differ between files" RESOLVER="$(printf '%b' "$(printf '%s' "$ALL_BLOCKS" | head -n1)")" -STUBS="$(mktemp -d)" +STUBS="$(mktemp -d)" && [ -d "$STUBS" ] || { echo "FAIL: could not create a temp dir"; exit 1; } trap 'rm -rf "$STUBS"' EXIT for stub in only-altimate/altimate only-altimate-code/altimate-code both/altimate both/altimate-code "relative dir/altimate"; do mkdir -p "$STUBS/$(dirname "$stub")" printf '#!/bin/sh\necho "ran %s"\n' "$(basename "$stub")" > "$STUBS/$stub" chmod +x "$STUBS/$stub" done -mkdir -p "$STUBS/neither" +mkdir -p "$STUBS/neither" "$STUBS/broken-altimate" +printf 'not a program\n' > "$STUBS/broken-altimate/altimate" # expect -# Runs from $STUBS without startup files, so relative PATH entries resolve and user config can't interfere. +# Runs from $STUBS without startup files and with only the stub dirs on PATH, so relative PATH +# entries resolve and neither user config nor system-installed binaries can interfere. expect() { local shell_cmd - case "$1" in zsh) shell_cmd=(zsh -f) ;; *) shell_cmd=(bash --noprofile --norc) ;; esac - out="$(cd "$STUBS" && env -u BASH_ENV -u ENV PATH="$2:/usr/bin:/bin" "${shell_cmd[@]}" -c "$3 + case "$1" in zsh) shell_cmd=("$(command -v zsh)" -f) ;; *) shell_cmd=("$(command -v bash)" --noprofile --norc) ;; esac + out="$(cd "$STUBS" && env -u BASH_ENV -u ENV PATH="$2" "${shell_cmd[@]}" -c "$3 $RESOLVER \"\$ALTIMATE_BIN\"" 2>&1)" status=$? @@ -65,6 +67,11 @@ for sh in bash zsh; do expect "$sh" "$STUBS/only-altimate" "$ALIAS_SETUP; altimate() { echo function; }" 0 'ran altimate' expect "$sh" "$STUBS/only-altimate" 'altimate-code() { echo function; }' 0 'ran altimate' expect "$sh" "$STUBS/only-altimate-code" 'shopt -s expand_aliases 2>/dev/null; alias altimate=altimate-code' 0 'ran altimate-code' + expect "$sh" "$STUBS/only-altimate-code" 'altimate-code() { echo function; }' 0 'ran altimate-code' + expect "$sh" "$STUBS/only-altimate-code" 'shopt -s expand_aliases 2>/dev/null; alias altimate-code="echo alias"' 0 'ran altimate-code' + expect "$sh" "$STUBS/neither" "$ALIAS_SETUP; altimate() { echo function; }" 127 'altimate-code CLI not found (tried altimate, altimate-code)' + expect "$sh" "$STUBS/broken-altimate:$STUBS/only-altimate-code" '' 0 'ran altimate-code' + expect "$sh" "$STUBS/broken-altimate" '' 127 'altimate-code CLI not found (tried altimate, altimate-code)' expect "$sh" "relative dir" '' 0 'ran altimate' done From 54196eb0cf2532c6e246ad63cc43b52aec9f6dcc Mon Sep 17 00:00:00 2001 From: Harish Kumar Date: Tue, 20 Oct 2026 07:40:29 +0530 Subject: [PATCH 3/4] fix: correct install-name notes and harden the resolver test npm and Homebrew installs expose both `altimate` and `altimate-code`; only older curl and PowerShell installs lack `altimate-code`. The review template no longer ends in a complete command. The resolver test fails on bare CLI command lines and runs under zsh. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- plugins/altimate-code/CHANGELOG.md | 2 +- plugins/altimate-code/README.md | 4 ++-- plugins/altimate-code/commands/altimate.md | 2 +- plugins/altimate-code/commands/review.md | 4 ++-- plugins/altimate-code/skills/altimate-code/SKILL.md | 2 +- plugins/altimate-code/skills/review/SKILL.md | 4 ++-- tests/resolve-cli.sh | 13 ++++++++++--- 8 files changed, 21 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cebd0f4..6bd5007 100644 --- a/README.md +++ b/README.md @@ -68,8 +68,8 @@ altimate-codex-plugin/ The delegation skill spawns `altimate-code` as a subprocess. Install the companion CLI: ```bash -npm install -g altimate-code # Node 20+; exposes `altimate-code` and `altimate` -curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes only `altimate` +npm install -g altimate-code # Node 20+; exposes `altimate` and `altimate-code` +curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes `altimate` ``` After install, run `altimate` once to configure your LLM provider auth and warehouse connections through the TUI. diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 43d3bfc..2d6a822 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [1.1.0] — 2026-10-19 ### Fixed -- The skills and slash commands now resolve the CLI as `altimate`, its canonical name since v0.7.1, and fall back to `altimate-code` for older npm installs. Standalone installs (curl, Homebrew, PowerShell) expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. +- The skills and slash commands now resolve the CLI as `altimate`, its canonical name since v0.7.1, and fall back to `altimate-code` for npm installs older than v0.7.1. Older curl and PowerShell installs expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. - Install guidance and recovery messages now list both the npm and curl install methods and point to `altimate` for first-run auth setup. - The CLI lookup ignores aliases and shell functions, skips a non-executable `altimate` in favour of a working `altimate-code`, and runs before `gh pr checkout` in PR reviews, so a missing CLI never switches your branch. Recovery messages name `altimate-code` for npm installs older than v0.7.1. diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index 0970cbe..aa08860 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -21,8 +21,8 @@ Adding the marketplace makes the plugin discoverable in the `/plugins` browser b The altimate-code CLI must be installed and configured on your PATH. Either install method works: ```bash -npm install -g altimate-code # requires Node 20+; exposes `altimate-code` and `altimate` -curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes only `altimate` +npm install -g altimate-code # requires Node 20+; exposes `altimate` and `altimate-code` +curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes `altimate` altimate # launch the TUI, then run /connect to configure your LLM provider ``` diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index 525d7e1..f91a44b 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -7,7 +7,7 @@ The user explicitly invoked `/altimate-code:altimate` to delegate this task to a Workflow (follow in order, no skipping): -1. **Verify altimate-code is installed.** There is no separate check: the run command in step 3 resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Either one is fine. If the run exits with `altimate-code CLI not found`, stop and tell the user: +1. **Verify altimate-code is installed.** There is no separate check: the run command in step 3 resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Either one is fine. If the run exits with `altimate-code CLI not found`, stop and tell the user: > altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install | bash`, then run `altimate` once to configure your provider/warehouse auth, then re-run `/altimate-code:altimate `. 2. **Pick the agent persona** based on the user's task shape. Start cheap and escalate on failure — fast-edit handles most dbt/SQL work at 10–20× lower cost than builder. diff --git a/plugins/altimate-code/commands/review.md b/plugins/altimate-code/commands/review.md index aee62fd..d9c7dfb 100644 --- a/plugins/altimate-code/commands/review.md +++ b/plugins/altimate-code/commands/review.md @@ -18,7 +18,7 @@ Run the `altimate-code review` CLI on the current dbt project and present the si 1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+) or 'curl -fsSL https://www.altimate.sh/install | bash', then run 'altimate' once to configure your provider and warehouse auth."` — then STOP. - The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash for ALTIMATE_NAME in altimate altimate-code; do @@ -26,7 +26,7 @@ Run the `altimate-code review` CLI on the current dbt project and present the si [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } - "$ALTIMATE_BIN" review # plus any scope/flags from below + ``` 2. **Confirm you are in a dbt project root** (`dbt_project.yml` present). If not, tell the user to `cd` there and STOP. diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index cb632b2..412d4ad 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -21,7 +21,7 @@ altimate-code is a CLI AI agent with 100+ purpose-built data engineering tools. ## You MUST follow this workflow -1. **Verify altimate-code is on PATH.** There is no separate check: the invocation below resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Either name is the same CLI. If the invocation exits with `altimate-code CLI not found`, jump to "Failure modes" below and stop. +1. **Verify altimate-code is on PATH.** There is no separate check: the invocation below resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Either name is the same CLI. If the invocation exits with `altimate-code CLI not found`, jump to "Failure modes" below and stop. 2. **Run altimate-code with the user's task** using the invocation below. Pass the user's request through verbatim — do not paraphrase or split it. 3. **Read the output file** and present it to the user as-is. diff --git a/plugins/altimate-code/skills/review/SKILL.md b/plugins/altimate-code/skills/review/SKILL.md index a157d4e..5ab0f51 100644 --- a/plugins/altimate-code/skills/review/SKILL.md +++ b/plugins/altimate-code/skills/review/SKILL.md @@ -29,7 +29,7 @@ description: >- 1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, jump to "Failure modes" below and stop. - The CLI ships under two names: the npm package exposes both `altimate-code` and `altimate`, while the standalone curl/Homebrew/PowerShell installers expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash for ALTIMATE_NAME in altimate altimate-code; do @@ -37,7 +37,7 @@ description: >- [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } - "$ALTIMATE_BIN" review # plus any scope/flags from below + ``` 2. **Determine review scope from the user's ask** using the table below. diff --git a/tests/resolve-cli.sh b/tests/resolve-cli.sh index c1b2950..5d85744 100755 --- a/tests/resolve-cli.sh +++ b/tests/resolve-cli.sh @@ -32,6 +32,13 @@ done [ "$(printf '%s' "$ALL_BLOCKS" | grep . | sort -u | grep -c .)" -eq 1 ] || fail "resolver blocks differ between files" RESOLVER="$(printf '%b' "$(printf '%s' "$ALL_BLOCKS" | head -n1)")" +# A command line that calls the CLI by name skips the resolver. User-typed `!` commands in prose are fine. +for entry in "${FILES[@]}"; do + file="${entry%:*}" + bare="$(grep -nE '^[[:space:]]*altimate(-code)? (run|review|workspace|link|auth|session)' "$file")" + [ -z "$bare" ] || fail "$file calls the CLI without the resolver: $bare" +done + STUBS="$(mktemp -d)" && [ -d "$STUBS" ] || { echo "FAIL: could not create a temp dir"; exit 1; } trap 'rm -rf "$STUBS"' EXIT for stub in only-altimate/altimate only-altimate-code/altimate-code both/altimate both/altimate-code "relative dir/altimate"; do @@ -51,9 +58,9 @@ expect() { out="$(cd "$STUBS" && env -u BASH_ENV -u ENV PATH="$2" "${shell_cmd[@]}" -c "$3 $RESOLVER \"\$ALTIMATE_BIN\"" 2>&1)" - status=$? - [ "$status" -eq "$4" ] && [ "$out" = "$5" ] \ - || fail "$1 / PATH=$2 / '${3:-no setup}': expected exit $4 '$5', got exit $status '$out'" + rc=$? + [ "$rc" -eq "$4" ] && [ "$out" = "$5" ] \ + || fail "$1 / PATH=$2 / '${3:-no setup}': expected exit $4 '$5', got exit $rc '$out'" } ALIAS_SETUP='shopt -s expand_aliases 2>/dev/null; alias altimate-code=altimate' From dc86f542889b02b035c17cdedf452b0570bb0374 Mon Sep 17 00:00:00 2001 From: Harish Kumar Date: Tue, 20 Oct 2026 07:41:59 +0530 Subject: [PATCH 4/4] fix: prefer altimate-code over altimate when resolving the CLI `altimate` is a generic name another tool may own, while `altimate-code` is unambiguous. The resolver now tries `altimate-code` first and falls back to `altimate` for standalone installs that expose only that name. Install-name notes, recovery messages and the README now describe the current installers accurately, and the test covers a foreign `altimate` ahead of a real `altimate-code`. Co-Authored-By: Claude Opus 5.5 --- README.md | 12 +++++++++--- plugins/altimate-code/CHANGELOG.md | 4 ++-- plugins/altimate-code/README.md | 8 ++++---- plugins/altimate-code/commands/altimate.md | 10 +++++----- plugins/altimate-code/commands/review.md | 8 ++++---- .../altimate-code/skills/altimate-code/SKILL.md | 16 ++++++++-------- plugins/altimate-code/skills/review/SKILL.md | 8 ++++---- tests/resolve-cli.sh | 13 ++++++++----- 8 files changed, 44 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 6bd5007..18fb111 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,16 @@ Codex plugin that delegates dbt and warehouse work to [`altimate-code`](https:// ## What this gives your Codex agent -One skill: **`altimate-code`** — routes tasks that touch live warehouse state, column lineage, cross-database work, query-cost attribution, schema diffs, PII detection, or FinOps reporting to the altimate-code subprocess. The skill body encodes: +Two skills and matching slash commands. **`altimate-code`** routes tasks that touch live warehouse state, column lineage, cross-database work, query-cost attribution, schema diffs, PII detection, or FinOps reporting to the altimate-code subprocess. The skill body encodes: -- how to resolve the CLI (`altimate` or `altimate-code`) and detect that it is not installed +- how to resolve the CLI (`altimate-code`, falling back to `altimate`) and detect that it is not installed - which agent persona (`fast-edit` / `analyst` / `builder`) to pick for the task shape - the exact non-interactive invocation with `--yolo` / `--output` / `--dir` - when to add `--continue` for follow-up tasks in a warm session - how to surface each failure mode to the user +**`review`** runs `altimate-code review` on dbt project changes (a local diff or a PR) and reports the findings. The slash commands `/altimate-code:altimate` and `/altimate-code:review` invoke the same flows explicitly. + The plugin also ships a `SessionStart` hook that emits a short routing hint into Codex's context so the model prefers delegation over reimplementing warehouse workflows with native tools. ## Install @@ -59,8 +61,12 @@ altimate-codex-plugin/ ├── hooks/ │ ├── hooks.json # SessionStart hook definition │ └── altimate-code-session-start.sh # hook script (routing hint) + ├── commands/ + │ ├── altimate.md # /altimate-code:altimate + │ └── review.md # /altimate-code:review └── skills/ - └── altimate-code/SKILL.md # the one delegation skill + ├── altimate-code/SKILL.md # delegation skill + └── review/SKILL.md # dbt change review skill ``` ## Companion CLI diff --git a/plugins/altimate-code/CHANGELOG.md b/plugins/altimate-code/CHANGELOG.md index 2d6a822..dee3712 100644 --- a/plugins/altimate-code/CHANGELOG.md +++ b/plugins/altimate-code/CHANGELOG.md @@ -7,9 +7,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [1.1.0] — 2026-10-19 ### Fixed -- The skills and slash commands now resolve the CLI as `altimate`, its canonical name since v0.7.1, and fall back to `altimate-code` for npm installs older than v0.7.1. Older curl and PowerShell installs expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. +- The skills and slash commands now resolve the CLI as `altimate-code` and fall back to `altimate`. curl and PowerShell installs from v0.7.1 on may expose only `altimate`, so the plugin previously reported "not installed" on machines where the CLI was present. `altimate-code` is tried first because a different tool may own the generic `altimate` name. - Install guidance and recovery messages now list both the npm and curl install methods and point to `altimate` for first-run auth setup. -- The CLI lookup ignores aliases and shell functions, skips a non-executable `altimate` in favour of a working `altimate-code`, and runs before `gh pr checkout` in PR reviews, so a missing CLI never switches your branch. Recovery messages name `altimate-code` for npm installs older than v0.7.1. +- The CLI lookup ignores aliases and shell functions, skips a non-executable match in favour of the other name, and runs before `gh pr checkout` in PR reviews, so a missing CLI never switches your branch. Recovery messages name `altimate` for installs without `altimate-code`. ## [1.0.0] — 2026-07-18 diff --git a/plugins/altimate-code/README.md b/plugins/altimate-code/README.md index aa08860..2413a5a 100644 --- a/plugins/altimate-code/README.md +++ b/plugins/altimate-code/README.md @@ -26,7 +26,7 @@ curl -fsSL https://www.altimate.sh/install | bash # standalone binary; exposes altimate # launch the TUI, then run /connect to configure your LLM provider ``` -The plugin invokes `altimate`, the CLI's canonical name, and falls back to `altimate-code` for npm installs older than v0.7.1, so standalone installs work without an `altimate-code` alias. +The plugin invokes `altimate-code`, which no other tool uses, and falls back to `altimate`, so standalone installs that expose only `altimate` still work. Or configure a provider via environment variable (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and 20+ others — see the [altimate-code docs](https://docs.altimate.sh)). @@ -61,11 +61,11 @@ Full details: **[PRIVACY.md](../../PRIVACY.md)** · Security policy and disclosu | Symptom | Fix | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider. | -| `Unauthorized` / `No provider configured` | Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | +| `Unauthorized` / `No provider configured` | Run `altimate-code` (`altimate` on installs without `altimate-code`) to open the TUI and reconfigure your provider via `/connect`, or set the provider API key env var. | | `Error: Unexpected error — Unknown: FileSystem.open (…altimate-code/log/opencode.log)` | Codex's default `workspace-write` sandbox blocks writes to `~/.local/share/altimate-code/log/`, where the CLI writes its log. Re-run with `codex exec --sandbox danger-full-access …`, or pass `-c 'sandbox_permissions=["disk-full-write-access"]'` on the specific invocation. Frequent users can raise the default in `~/.codex/config.toml`. Codex has no per-plugin sandbox-permission declaration in its manifest schema today, so this is a per-invocation flag. | -| Task hangs for several minutes | Open `altimate` (`altimate-code` on npm installs older than v0.7.1) to check for a pending prompt in the TUI, or re-run specifying a known-good model. | +| Task hangs for several minutes | Open `altimate-code` (`altimate` on installs without `altimate-code`) to check for a pending prompt in the TUI, or re-run specifying a known-good model. | | Empty result | The task may be too ambiguous — restate with the target table, expected columns, or time window. | -| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate` TUI (`altimate-code` on npm installs older than v0.7.1) or `profiles.yml`. | +| `UNKNOWN_USER` / `Database does not exist` mid-run | The CLI connects but your warehouse credentials don't match this project — reconfigure warehouse auth in the `altimate-code` TUI (`altimate` on installs without `altimate-code`) or `profiles.yml`. | | Plugin installed but never delegates | Confirm the SessionStart hook is trusted — Codex asks on first use; if you skipped it, uninstall and reinstall from `/plugins`. | | Plugin doesn't appear in `/plugins` | Confirm the marketplace is registered: `codex plugin marketplace add AltimateAI/altimate-codex-plugin`, then re-open `/plugins`. | diff --git a/plugins/altimate-code/commands/altimate.md b/plugins/altimate-code/commands/altimate.md index f91a44b..0af4fca 100644 --- a/plugins/altimate-code/commands/altimate.md +++ b/plugins/altimate-code/commands/altimate.md @@ -7,7 +7,7 @@ The user explicitly invoked `/altimate-code:altimate` to delegate this task to a Workflow (follow in order, no skipping): -1. **Verify altimate-code is installed.** There is no separate check: the run command in step 3 resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Either one is fine. If the run exits with `altimate-code CLI not found`, stop and tell the user: +1. **Verify altimate-code is installed.** There is no separate check: the run command in step 3 resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`; curl and PowerShell installs from v0.7.1 on may expose only `altimate`, and installs older than v0.7.1 expose only `altimate-code`. The lookup tries `altimate-code` first, because no other tool uses that name, and falls back to `altimate`. Either one is fine. If the run exits with `altimate-code CLI not found`, stop and tell the user: > altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install | bash`, then run `altimate` once to configure your provider/warehouse auth, then re-run `/altimate-code:altimate `. 2. **Pick the agent persona** based on the user's task shape. Start cheap and escalate on failure — fast-edit handles most dbt/SQL work at 10–20× lower cost than builder. @@ -31,11 +31,11 @@ Workflow (follow in order, no skipping): $ARGUMENTS ALTIMATE_TASK )" - for ALTIMATE_NAME in altimate altimate-code; do + for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done - [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" "$ALTIMATE_BIN" run "$TASK" \ @@ -52,11 +52,11 @@ Workflow (follow in order, no skipping): $ARGUMENTS ALTIMATE_TASK )" - for ALTIMATE_NAME in altimate altimate-code; do + for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done - [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" "$ALTIMATE_BIN" run "$TASK" \ diff --git a/plugins/altimate-code/commands/review.md b/plugins/altimate-code/commands/review.md index d9c7dfb..15c20cf 100644 --- a/plugins/altimate-code/commands/review.md +++ b/plugins/altimate-code/commands/review.md @@ -18,14 +18,14 @@ Run the `altimate-code review` CLI on the current dbt project and present the si 1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, tell the user: `"altimate-code is not installed. Install with 'npm install -g altimate-code' (Node 20+) or 'curl -fsSL https://www.altimate.sh/install | bash', then run 'altimate' once to configure your provider and warehouse auth."` — then STOP. - The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`; curl and PowerShell installs from v0.7.1 on may expose only `altimate`, and installs older than v0.7.1 expose only `altimate-code`. The lookup tries `altimate-code` first, because no other tool uses that name, and falls back to `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash - for ALTIMATE_NAME in altimate altimate-code; do + for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done - [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } ``` @@ -65,7 +65,7 @@ Anything else (`--manifest`, `--cwd`) only if the user explicitly requested it o | Symptom | Message to user | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth." | -| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to reconfigure, or re-run with `--no-ai`." | +| `Unauthorized: Incorrect auth token` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` (`altimate` on installs without `altimate-code`) to reconfigure, or re-run with `--no-ai`." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` needs git to compute the diff." | | No `dbt_project.yml` | "No dbt project detected at this path. Run from the directory with `dbt_project.yml`." | | Output mentions `DEGRADED — lint-only` | Present verbatim; do NOT silently upgrade a degraded run to a full verdict. | diff --git a/plugins/altimate-code/skills/altimate-code/SKILL.md b/plugins/altimate-code/skills/altimate-code/SKILL.md index 412d4ad..9c83890 100644 --- a/plugins/altimate-code/skills/altimate-code/SKILL.md +++ b/plugins/altimate-code/skills/altimate-code/SKILL.md @@ -21,7 +21,7 @@ altimate-code is a CLI AI agent with 100+ purpose-built data engineering tools. ## You MUST follow this workflow -1. **Verify altimate-code is on PATH.** There is no separate check: the invocation below resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Either name is the same CLI. If the invocation exits with `altimate-code CLI not found`, jump to "Failure modes" below and stop. +1. **Verify altimate-code is on PATH.** There is no separate check: the invocation below resolves the CLI first, ignoring aliases and shell functions, and exits 127 with `altimate-code CLI not found` before doing anything else. The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`; curl and PowerShell installs from v0.7.1 on may expose only `altimate`, and installs older than v0.7.1 expose only `altimate-code`. The lookup tries `altimate-code` first, because no other tool uses that name, and falls back to `altimate`. Either name is the same CLI. If the invocation exits with `altimate-code CLI not found`, jump to "Failure modes" below and stop. 2. **Run altimate-code with the user's task** using the invocation below. Pass the user's request through verbatim — do not paraphrase or split it. 3. **Read the output file** and present it to the user as-is. @@ -55,11 +55,11 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" -for ALTIMATE_NAME in altimate altimate-code; do +for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done -[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } +[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" "$ALTIMATE_BIN" run "$TASK" \ @@ -91,11 +91,11 @@ TASK="$(cat <<'ALTIMATE_TASK' ALTIMATE_TASK )" -for ALTIMATE_NAME in altimate altimate-code; do +for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done -[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } +[ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } umask 077 OUTPUT_FILE="$(mktemp -t altimate-result.XXXXXX.md)" "$ALTIMATE_BIN" run "$TASK" \ @@ -117,10 +117,10 @@ When altimate-code returns an error, **report the error to the user and STOP**. | Symptom | What to tell the user — verbatim | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure auth. Then re-run your request." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) in your terminal to open the TUI and reconfigure your provider, then re-run your request." | -| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate` (`altimate-code` on npm installs older than v0.7.1) to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` (`altimate` on installs without `altimate-code`) in your terminal to open the TUI and reconfigure your provider, then re-run your request." | +| Process hangs >5 min | "altimate-code is unresponsive. Try `altimate-code` (`altimate` on installs without `altimate-code`) to inspect the TUI for an open prompt, or re-run with `--model anthropic/claude-sonnet-4-6` to force a known-good model." | | Output file empty | "altimate-code returned without producing output. The task may be too ambiguous — please restate with more detail (target table, expected columns, time window)." | -| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via the `altimate` TUI (`altimate-code` on npm installs older than v0.7.1)." | +| Warehouse error mid-run (`UNKNOWN_USER`, `Database does not exist`) | "altimate-code can connect but the warehouse credentials it has are wrong for this project. Configure provider/warehouse auth via the `altimate-code` TUI (`altimate` on installs without `altimate-code`)." | In every row, the instruction to the user is the action — you do not retry the task with native tools. If the user fixes the underlying issue and asks again, you delegate again. diff --git a/plugins/altimate-code/skills/review/SKILL.md b/plugins/altimate-code/skills/review/SKILL.md index 5ab0f51..6415a53 100644 --- a/plugins/altimate-code/skills/review/SKILL.md +++ b/plugins/altimate-code/skills/review/SKILL.md @@ -29,14 +29,14 @@ description: >- 1. **Verify altimate-code is on PATH.** There is no separate check: the resolver below runs first in the same shell command as the review, before any `gh pr checkout`. If it exits 127 with `altimate-code CLI not found`, jump to "Failure modes" below and stop. - The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`, while older curl and PowerShell installs expose only `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: + The CLI ships under two names: npm and Homebrew installs expose both `altimate` and `altimate-code`; curl and PowerShell installs from v0.7.1 on may expose only `altimate`, and installs older than v0.7.1 expose only `altimate-code`. The lookup tries `altimate-code` first, because no other tool uses that name, and falls back to `altimate`. Every review command below runs through `"$ALTIMATE_BIN"`, in the same shell command as this resolver (shell state does not persist between commands). The lookup ignores aliases and shell functions, so a user alias such as `alias altimate-code=altimate` cannot be captured as the binary path: ```bash - for ALTIMATE_NAME in altimate altimate-code; do + for ALTIMATE_NAME in altimate-code altimate; do ALTIMATE_BIN="$(unalias "$ALTIMATE_NAME" 2>/dev/null; unset -f "$ALTIMATE_NAME" 2>/dev/null; command -v "$ALTIMATE_NAME")" [ -x "$ALTIMATE_BIN" ] && break || ALTIMATE_BIN= done - [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate, altimate-code)" >&2; exit 127; } + [ -n "$ALTIMATE_BIN" ] || { echo "altimate-code CLI not found (tried altimate-code, altimate)" >&2; exit 127; } ``` @@ -80,7 +80,7 @@ description: >- | Symptom | Message to the user | |---|---| | `altimate-code CLI not found` (neither `altimate` nor `altimate-code` on PATH) | "altimate-code is not installed. Install with `npm install -g altimate-code` (Node 20+) or `curl -fsSL https://www.altimate.sh/install \| bash`, then run `altimate` once to configure your provider and warehouse auth. Then re-run the review." | -| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate` (`altimate-code` on npm installs older than v0.7.1) to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | +| `Unauthorized: Incorrect auth token` / `No provider configured` | "altimate-code's LLM provider auth is misconfigured. Run `altimate-code` (`altimate` on installs without `altimate-code`) to reconfigure — or re-run with `--no-ai` to skip the LLM lane entirely and get a deterministic-only review." | | `fatal: not a git repository` | "This directory isn't a git repo. `altimate-code review` computes the diff via git — run from a dbt project inside a git worktree." | | No `dbt_project.yml` found | "No dbt project detected at this path. The review needs a dbt project to compile models against. Run from the directory containing `dbt_project.yml`." | | Output says `DEGRADED — lint-only` | Present that note verbatim. Do not silently upgrade a degraded run to a full verdict. | diff --git a/tests/resolve-cli.sh b/tests/resolve-cli.sh index 5d85744..b01b517 100755 --- a/tests/resolve-cli.sh +++ b/tests/resolve-cli.sh @@ -46,8 +46,9 @@ for stub in only-altimate/altimate only-altimate-code/altimate-code both/altimat printf '#!/bin/sh\necho "ran %s"\n' "$(basename "$stub")" > "$STUBS/$stub" chmod +x "$STUBS/$stub" done -mkdir -p "$STUBS/neither" "$STUBS/broken-altimate" +mkdir -p "$STUBS/neither" "$STUBS/broken-altimate" "$STUBS/broken-altimate-code" printf 'not a program\n' > "$STUBS/broken-altimate/altimate" +printf 'not a program\n' > "$STUBS/broken-altimate-code/altimate-code" # expect # Runs from $STUBS without startup files and with only the stub dirs on PATH, so relative PATH @@ -68,17 +69,19 @@ for sh in bash zsh; do command -v "$sh" >/dev/null || { echo "skip: $sh not installed"; continue; } expect "$sh" "$STUBS/only-altimate" '' 0 'ran altimate' expect "$sh" "$STUBS/only-altimate-code" '' 0 'ran altimate-code' - expect "$sh" "$STUBS/both" '' 0 'ran altimate' - expect "$sh" "$STUBS/neither" '' 127 'altimate-code CLI not found (tried altimate, altimate-code)' + expect "$sh" "$STUBS/both" '' 0 'ran altimate-code' + expect "$sh" "$STUBS/only-altimate:$STUBS/only-altimate-code" '' 0 'ran altimate-code' + expect "$sh" "$STUBS/neither" '' 127 'altimate-code CLI not found (tried altimate-code, altimate)' expect "$sh" "$STUBS/only-altimate" "$ALIAS_SETUP" 0 'ran altimate' expect "$sh" "$STUBS/only-altimate" "$ALIAS_SETUP; altimate() { echo function; }" 0 'ran altimate' expect "$sh" "$STUBS/only-altimate" 'altimate-code() { echo function; }' 0 'ran altimate' expect "$sh" "$STUBS/only-altimate-code" 'shopt -s expand_aliases 2>/dev/null; alias altimate=altimate-code' 0 'ran altimate-code' expect "$sh" "$STUBS/only-altimate-code" 'altimate-code() { echo function; }' 0 'ran altimate-code' expect "$sh" "$STUBS/only-altimate-code" 'shopt -s expand_aliases 2>/dev/null; alias altimate-code="echo alias"' 0 'ran altimate-code' - expect "$sh" "$STUBS/neither" "$ALIAS_SETUP; altimate() { echo function; }" 127 'altimate-code CLI not found (tried altimate, altimate-code)' + expect "$sh" "$STUBS/neither" "$ALIAS_SETUP; altimate() { echo function; }" 127 'altimate-code CLI not found (tried altimate-code, altimate)' expect "$sh" "$STUBS/broken-altimate:$STUBS/only-altimate-code" '' 0 'ran altimate-code' - expect "$sh" "$STUBS/broken-altimate" '' 127 'altimate-code CLI not found (tried altimate, altimate-code)' + expect "$sh" "$STUBS/broken-altimate-code:$STUBS/only-altimate" '' 0 'ran altimate' + expect "$sh" "$STUBS/broken-altimate" '' 127 'altimate-code CLI not found (tried altimate-code, altimate)' expect "$sh" "relative dir" '' 0 'ran altimate' done