Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e2ceb6d
feat(free): add free-tier gateway client and registration endpoint
anandgupta42 Aug 6, 2026
4190682
feat(provider): register the altimate-free provider
anandgupta42 Aug 6, 2026
a7b672d
feat(telemetry): free-tier funnel events
anandgupta42 Aug 6, 2026
209a6a9
feat(tui): free Gemini Flash disclosure and picker rows
anandgupta42 Aug 6, 2026
b827f9c
docs: document the free Gemini Flash model
anandgupta42 Aug 6, 2026
38256c6
fix(free): rotate on revocation, dedupe registration, fix choice doub…
anandgupta42 Aug 6, 2026
3014f7d
fix(free): send X-Session-Id on free-tier requests
anandgupta42 Aug 6, 2026
2b25be2
fix(free): harden registration, error classification, and dismissal race
anandgupta42 Aug 6, 2026
ef1148d
test(free): client-side E2E harness for the free tier
anandgupta42 Aug 6, 2026
76594e9
test(free): assert output-side redaction, fix ARG_MAX trace lookup
anandgupta42 Aug 6, 2026
0ec2de7
fix(free): sanitize cli_version to the gateway's grammar
anandgupta42 Aug 6, 2026
346ad86
feat(free): distinct messages for the two free-tier 429s
anandgupta42 Aug 6, 2026
491310d
fix(free): fail fast on an oversized request instead of retrying
anandgupta42 Aug 6, 2026
89f4e92
docs: record what was built and what the build changed
anandgupta42 Aug 6, 2026
f83f0ed
fix(free): close the credential-exfiltration and consent-bypass paths
anandgupta42 Aug 6, 2026
3832bbe
fix(free): await provider reload before selecting the free model
anandgupta42 Aug 6, 2026
ade3a7e
docs: record the cache-prefix finding
anandgupta42 Aug 6, 2026
b036976
fix: serialize credential writes and free-tier key rotation
anandgupta42 Aug 7, 2026
443a464
docs: correct commit counts and record the follow-ups
anandgupta42 Aug 7, 2026
1da20c5
perf: order the system prompt stable to volatile for prefix caching
anandgupta42 Aug 7, 2026
5944c74
fix(mcp): emit tools in a deterministic order across process restarts
anandgupta42 Aug 7, 2026
5b0994d
docs: settle the cache ceiling with measurements
anandgupta42 Aug 7, 2026
810a030
fix(skill): order skills by codepoint so the block is byte-stable acr…
anandgupta42 Aug 7, 2026
1b6fdeb
docs: record the prefix sweep findings
anandgupta42 Aug 7, 2026
80647d1
fix(auth): serialize every auth.json read-modify-write behind one sto…
anandgupta42 Aug 7, 2026
df029d8
fix(core): make the atomic writer honour mode, typed errors, and syml…
anandgupta42 Aug 7, 2026
27e1cc8
fix(prompt): restore knowledge before repository instructions
anandgupta42 Aug 7, 2026
9dc4ff0
fix: deterministic tool/skill ordering and two late-resume races
anandgupta42 Aug 7, 2026
2ca7adf
test(free): fix a 1-in-16 flake in the consent-capability test
anandgupta42 Aug 7, 2026
f400c92
fix(auth): route both auth.json writers through one atomic writer
anandgupta42 Aug 7, 2026
1e67d74
fix(auth): one credential schema for both Auth implementations
anandgupta42 Aug 7, 2026
89aabac
fix(core): canonical path resolution, and stop swallowing realpath an…
anandgupta42 Aug 7, 2026
7d0cf33
test: make four regression tests actually fail against the bugs they …
anandgupta42 Aug 7, 2026
a46a1b3
chore: wrap two upstream-shared edits in altimate_change markers
anandgupta42 Aug 7, 2026
72a3f82
fix(provider): drop free-tier config at ingestion, not at each consumer
anandgupta42 Aug 7, 2026
0095ac4
fix(auth): resolve the store once per mutation and use it for lock AN…
anandgupta42 Aug 7, 2026
2e91975
fix(free): make 401 recovery a bounded loop instead of a single retry
anandgupta42 Aug 7, 2026
0408a83
fix: one code-point comparator for every prompt-facing sort
anandgupta42 Aug 7, 2026
9614d8d
chore: wrap the configFor lookup in altimate_change markers
anandgupta42 Aug 7, 2026
bebcb43
fix(free): pin the provider record and keep config out of default sel…
anandgupta42 Aug 7, 2026
72a8575
fix(auth): couple resolution, read, lock and write; stop reading erro…
anandgupta42 Aug 7, 2026
4bcb209
fix(free): never resend a key this request already proved dead
anandgupta42 Aug 7, 2026
c372f71
refactor(free): derive every consumer from one denial
anandgupta42 Aug 17, 2026
f3f11e1
fix(mcp): sort servers and tools by code point, not UTF-16 code unit
anandgupta42 Aug 17, 2026
71f2110
test(provider): cover the two free-tier fixes that had no test
anandgupta42 Aug 17, 2026
862661f
docs: record what seven review rounds found
anandgupta42 Aug 17, 2026
c72c3f2
docs: notes for a human reviewer, and the strongest form of the rever…
anandgupta42 Aug 17, 2026
f1fab59
docs: the carrier enumeration, and what verified actually meant
anandgupta42 Aug 17, 2026
1c80f39
docs: round 5 — the enumeration held, the per-field claims did not
anandgupta42 Aug 17, 2026
9fd5e8b
docs: the sweep test, and what it does not cover
anandgupta42 Aug 17, 2026
3056094
Merge remote-tracking branch 'origin/main' into feat/free-gemini-flash
anandgupta42 Aug 18, 2026
d4af374
test(free): assemble the AWS canary so scanners do not match the source
anandgupta42 Aug 18, 2026
ba97e7c
test(free): replace a captured key hash, and stop the leak check goin…
anandgupta42 Aug 18, 2026
810dc11
test(upstream): pin the skills sort by property, not by its old line
anandgupta42 Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions docs/docs/configure/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ Managed LLM access with dynamic routing across Sonnet 4.6, Opus 4.6, GPT-5.4, GP
```json
{
"provider": {
"altimate": {}
"altimate-backend": {}
},
"model": "altimate/auto"
"model": "altimate-backend/altimate-default"
}
```

Expand All @@ -46,6 +46,27 @@ For pricing, security, and data handling details, see the [Altimate LLM Gateway
!!! tip "Automatic model selection"
When Altimate credentials are configured and no model is explicitly chosen, the Altimate LLM Gateway is selected automatically. You can override this by setting `model` in your config or by restricting the `provider` section to specific providers only.

## Gemini Flash (Free)

A hosted Gemini Flash model we pay for. No signup, no API key: pick **Gemini Flash (Free)** in the model picker, accept the disclosure, and the CLI registers itself with our gateway and stores a short-lived key. The key rotates silently when it expires.

```json
{
"model": "altimate-free/gemini-flash-free"
}
```

!!! warning "What you agree to"
Free model — requests and responses are logged and may be used to improve Altimate's products and services. Don't send secrets or confidential code. No signup required.

Nothing is sent to the gateway until you accept that disclosure: the install identifier is created in the same step that registers it, so an install that never opts in never contacts the free-tier gateway at all. Usage is subject to per-install daily limits; when a limit is hit, requests are rejected until it resets.

Point the CLI at a different gateway (for local development against your own deployment) with `ALTIMATE_FREE_GATEWAY_URL`:

```bash
ALTIMATE_FREE_GATEWAY_URL=http://localhost:4000 altimate-code
```

## Anthropic

```json
Expand Down
8 changes: 6 additions & 2 deletions docs/docs/reference/telemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ We collect the following categories of events:
| `validator_retries_exhausted` | A session terminated with unresolved validator failures after exhausting the synthetic-retry budget — names of the failing validators (no failure body content). |
| `onboarding_started` | The first-run setup gate opened (fresh launch with no usable model). |
| `model_picker_shown` | The provider picker was displayed. `trigger` distinguishes the first run from `/connect`, from declining Big Pickle, and from the prompt gate. |
| `provider_selected` | A provider row was chosen — `altimate_gateway`, `anthropic`, `openai`, `google`, `big_pickle`, `search_all`, or `other` for anything outside the curated five. `provider_id` carries the raw id only for publicly-known providers, so a provider you named yourself in config is reported as `other` with no name attached. `via_search` marks a pick made inside the full catalogue after choosing "Search all providers…". **Choosing search emits this event twice for one user** — once as `search_all`, then again with the provider actually chosen — so count distinct users or filter on `via_search`, not raw event count. Recorded at the moment of choice, so a sign-in that is then cancelled still counts. |
| `provider_selected` | A provider row was chosen — `altimate_gateway`, `altimate_free`, `anthropic`, `openai`, `google`, `big_pickle`, `search_all`, or `other` for anything outside the curated set. `provider_id` carries the raw id only for publicly-known providers, so a provider you named yourself in config is reported as `other` with no name attached. `via_search` marks a pick made inside the full catalogue after choosing "Search all providers…". **Choosing search emits this event twice for one user** — once as `search_all`, then again with the provider actually chosen — so count distinct users or filter on `via_search`, not raw event count. Recorded at the moment of choice, so a sign-in that is then cancelled still counts. |
| `big_pickle_confirm_shown` / `big_pickle_choice` | The Big Pickle interstitial was shown, and what the user decided (`accept`/`cancel`). |
| `free_gemini_confirm_shown` / `free_gemini_choice` | The Gemini Flash (Free) disclosure interstitial was shown, and what the user decided (`accept`/`cancel`). Every dismissal that is not an explicit accept — Escape, click-away, picking another row — is recorded as `cancel`. |
| `free_gemini_register_result` | The outcome of the free-tier registration that runs after an `accept`: `success`, `rate_limited` (gateway velocity limit), `unavailable` (gateway maintenance or kill switch), `network` (gateway unreachable), or `error`. Never carries error text. |
| `gateway_device_code_issued` | The Altimate Gateway authorize URL was built and the browser open attempted. **Name note:** the flow is a browser loopback OAuth — there is no device code. The name follows the original event spec. |
| `gateway_auth_completed` / `gateway_auth_failed` | Gateway sign-in outcome. `reason` is `timeout`, `denied`, or `error` — never the underlying message, which can contain the instance name. An unrecognised callback state does not reject the pending attempt, so a CSRF mismatch surfaces as `timeout`. |
| `instance_connected` | Credentials received and saved. `time_to_connect_ms` runs from the start of the authorize call, so it includes the browser launch. No instance or tenant name is sent. |
Expand All @@ -65,7 +67,7 @@ We collect the following categories of events:
| `activation_menu_shown` | The activation menu was (very likely) rendered. `variant` is `warehouse` or `no_data`. **Derived** — see the note below. |
| `activation_job_selected` / `first_job_completed` | Which activation job the user started and, where observable, finished. Completion is reported only for the job that was actually selected, so the two form a coherent pair. **Derived** — see the note below. |
| `first_prompt_sent` | The user's first typed message in an onboarding session. Slash commands are excluded, so the hidden `/onboard-connect` submission does not count. |
| `onboarding_abandoned` | The CLI exited during a first run without connecting. `last_stage` is the furthest point reached: `started`, `model_picker`, `provider_setup`, `big_pickle_confirm`, or `gateway_auth`. (`connected` is a funnel position but never a `last_stage` — reaching it means the run completed, which is not an abandonment.) Only emitted for a genuine first run — opening `/connect` as an existing user does not enter the funnel, and abandonment after setup completes is out of scope by definition. Emitted on the exit path under a bounded flush, so the measured rate is a lower bound — see [Delivery & Reliability](#delivery--reliability). |
| `onboarding_abandoned` | The CLI exited during a first run without connecting. `last_stage` is the furthest point reached: `started`, `model_picker`, `provider_setup`, `big_pickle_confirm`, `free_gemini_confirm`, or `gateway_auth`. (`connected` is a funnel position but never a `last_stage` — reaching it means the run completed, which is not an abandonment.) Only emitted for a genuine first run — opening `/connect` as an existing user does not enter the funnel, and abandonment after setup completes is out of scope by definition. Emitted on the exit path under a bounded flush, so the measured rate is a lower bound — see [Delivery & Reliability](#delivery--reliability). |
| `review_run` | A dbt/SQL review completed or failed — `invocation` (`cli` for `altimate-code review`, `tool` for the `dbt_pr_review` tool), status, duration, and on success the verdict, the pre-gating verdict, mode, risk tier, and finding counts by severity and by category. No file paths, model or column names, finding titles or bodies, SQL, diff content, or repository/branch/PR names. |
| `review_post_outcome` | Whether a review was published to GitHub — `not_requested`, `not_attempted`, `target_unresolved`, `full`, `partial`, or `summary_failed`, plus duration. Emitted on the **CLI path only** — the `dbt_pr_review` tool completes reviews but never publishes, so a `review_run` with `invocation: tool` has no post event and that is not a failure. Within the CLI path there is exactly one per **completed** review: a review that failed emits `review_run: failed` and no post event, so absence there means the review failed rather than that an event was lost. `not_attempted` is publication requested but never reached (a bad `--output` path, a stdout write error). No repository, PR, or comment content. |

Expand Down Expand Up @@ -171,6 +173,8 @@ Altimate Code uses two types of anonymous identifiers for analytics, depending o

Both identifiers are only sent when telemetry is enabled. Disable telemetry entirely with `ALTIMATE_TELEMETRY_DISABLED=true` or the config option above.

The [Gemini Flash (Free)](../configure/providers.md#gemini-flash-free) tier uses a **separate** identifier, deliberately not the machine ID above: a random secret minted only when you accept its disclosure, stored with your other credentials, and sent to the free-tier gateway only as a SHA-256 hash. It exists to hold that install's usage budget, and it is never used for telemetry — the two datasets are not joined. Declining the free model, or never opening it, means the identifier is never created.

### CLI Authentication Flow

When you sign in using the CLI browser auth flow (`altimate auth login`), the anonymous machine ID (a random UUID persisted at `~/.altimate/machine-id` — a device/installation identifier, reused across sessions) is included in the authorization URL and associated with your account in product analytics. This is used solely to correlate CLI install events with authenticated accounts in aggregate funnel analytics — it is not used for advertising or cross-site tracking. Your telemetry opt-out suppresses this: when you disable telemetry — via `ALTIMATE_TELEMETRY_DISABLED=true` **or** the `telemetry.disabled` config option — the machine ID is omitted from the authorization URL entirely. The machine ID is associated with your account in PostHog for this funnel analysis, separate from the Azure Application Insights pipeline used for other CLI telemetry events.
Expand Down
Loading
Loading