Repository navigation
Description
Provider naming & ownership convention — design (Drew directive 2026-11-06)
Drew: "any other alignments for the providers as a whole. if there's a cleaner structure like direct/ or leading _ or _.provider or something. if we know it's ours then we don't need to say direct."
This issue is the design home for the provider-id convention. It broadens #1817 (claude-code → claude-direct) — no renames are executed here; Drew rules on the convention first, then the rename map below is applied as one coordinated pass.
Principle
A provider id should say whose it is. "-direct" describes a mechanism (wire emulation); if the id itself marks fleet ownership, the mechanism suffix is noise. Official upstream ids are never renamed.
Inventory (verified 2026-11-06: fork packages/ai/src/providers/ + fleet config developing-today/code .opencode/opencode.jsonc)
OURS — fleet-built, fork source (header comments state the direct-provider pattern verbatim):
| Config id (runtime) | Source id (ProviderID.make) |
Package | Notes |
|---|---|---|---|
claude-code |
claude-code |
providers/claude-code.ts |
wire emulation of the Claude Code CLI (anomalyco#6117) |
antigravity-direct |
antigravity |
providers/antigravity.ts |
config id ≠ source id — the split this convention ends |
vibe-direct |
vibe |
providers/vibe.ts |
config id ≠ source id, same split |
commandcode |
commandcode |
providers/commandcode.ts |
quota registry spells it command-code — second split |
meta (native pkg) |
meta |
providers/meta.ts |
meta currently binds @ai-sdk/openai → api.meta.ai instead — which "meta" is canonical must be settled before any rename (see map) |
OURS — fleet-configured doors (no fork code; official SDK packages + our config):
| Config id | Binding | Notes |
|---|---|---|
muse-direct |
@ai-sdk/openai → local muse-proxy 127.0.0.1:18747 |
fleet-created id; fronts a local proxy (infra fate tracked by the decommission pass, not this issue) |
opendesign |
@ai-sdk/openai-compatible → amr-link.open-design.ai |
names a third-party service |
cline-pass |
@ai-sdk/openai-compatible |
names a third-party service |
OFFICIAL — upstream, used as-is, ids untouchable: the rest of packages/ai/src/providers/ (anthropic, openai, mistral, deepseek, google, groq, openrouter, xai, zai, … 45 source ids total). Fleet-used today include openai, mistral, deepseek; groq/openrouter are defined but disabled. A separate audit (running in parallel) verifies no fleet edits live inside official provider files and that no used provider spawns a binary.
RETIRED ids (definitions retained, disabled, per the switchboard rule): antigravity-ls, antigravity-agy. Plus catalog tombstones in disabled_providers (google, google-vertex, cloudflare-ai-gateway, cloudflare-workers-ai, github-copilot) whose definitions are deleted but whose entries must stay.
Quota-layer ids (packages/ai/src/quota/providers/): antigravity, claude (serves provider claude-code), cline-pass, codex (the OpenAI plan pool), command-code, deepseek, groq, meta, mistral, opencode-go, opendesign, openrouter, turso. Two of these already disagree with their provider ids (claude, command-code) — the convention pass should unify them via the alias mechanism, not leave a third naming layer.
Constraints (why most shapes fail)
- The provider id is the first segment of every leaf string
provider/modelin routes, sessions, and config. An id containing/is mechanically impossible — the parser splits on the first slash. This kills thedirect/namespace shape outright. - Ids are keys in: config provider blocks,
disabled_providers, route leaves,session_message/route_healthrows, the quota registry (ids + aliases), the pm-stack quota gatherer, logs and dashboards. A rename is a coordinated config + registry change; historical DB rows keep the old id (they are history, not pointers). - Id grammar in the wild is lowercase words + dashes (
zai-coding-plan). Any marker must survive JSON keys, URLs, shell, and SQL unchanged.
Candidate evaluation
| Shape | Example | Verdict |
|---|---|---|
| Slash namespace | direct/claude |
Impossible — slash is the leaf separator |
| Mechanism prefix | direct-claude |
Says "direct", not "ours" — the thing Drew wants to drop |
| Leading underscore | _claude |
Legal, sorts first, clearly non-catalog; but reads as private/internal in most ecosystems and looks like a temporary hack in logs/URLs |
.provider suffix |
claude.provider |
Dots already occur in model ids (claude-haiku-5.5), so leaf strings get harder to eyeball; and it says "is a provider" (everything here is), not "ours" |
_. compound |
_.claude |
Stacks both oddities; same private connotation |
Ownership prefix dt- |
dt-claude |
Recommended. Short, dash-grammar native, unmistakably ours (developing-today), collision with any future upstream id is essentially impossible, the whole family sorts/groups together everywhere ids are listed |
Fallback if Drew prefers plain English over the org mark: ours- (same mechanics, one syllable longer, slightly more generic if configs are ever shared).
Rename map (under the recommended dt- convention)
| Current | Proposed | Touches |
|---|---|---|
claude-code |
dt-claude |
source id, config block, 4+ leaves, quota id claude becomes an alias of dt-claude |
antigravity-direct / antigravity |
dt-antigravity |
config + source ids converge; leaves; quota id follows |
vibe-direct / vibe |
dt-vibe |
config + source converge; mistral-plan membership |
commandcode |
dt-commandcode |
source + config; quota command-code becomes alias — spelling split closed |
meta (native pkg) |
dt-meta |
meta = SDK door to api.meta.ai while the native package is unused by that block. Rename must not silently rebind the config door |
muse-direct |
dt-muse |
config id only (door definition unchanged) |
opendesign, cline-pass |
unchanged (proposal) | fleet-configured but they name third-party services, like openrouter; mark them only if Drew wants every fleet-config id badged |
antigravity-ls, antigravity-agy |
unchanged | retired + disabled; renaming dead definitions is churn with zero runtime effect |
| all official ids | unchanged | by the principle above |
Migration notes
- Order: fork first (source
ProviderID.make+ quota registry, keeping old ids as quota aliases for continuity), then the code-repo config (provider blocks,disabled_providers, every route leaf), then deploy + server restart, verified viaGET /api/provider. - The config file's deployed copies must stay byte-identical through the change (single repo edit + normal deploy; regenerate the runtime overlay as part of the same pass — the overlay staleness bit us on 2026-11-06).
- Historical
session_message/route_healthrows keep old ids; dashboards should treat the rename map as the join key for pre/post comparisons. - Docs/comments that narrate the old ids get a dated rename note, not a rewrite of history.
- One PR per repo, merge commits only; the whole map lands atomically enough that no route ever names a non-existent provider (config and fork deploy together, or config ships with both ids defined for one release window if sequencing demands it).
Related workstreams (not this issue)
- Audit: fleet edits inside official provider files (report + follow-ups).
- Audit: binary-required providers among those the fleet uses (wire-only doctrine check).
- Proxy-infra decommission: the retired proxy lineage (
bin/*-proxy.mjsfamily, :18749/:18751 units) across opencode / openchamber / code.
Drew rules on: (a) dt- vs ours- vs another marker; (b) whether fleet-configured service doors (opendesign, cline-pass) get badged; (c) canonical "meta" before its rename line is scheduled.
Acceptance criteria
- A single provider naming & ownership convention is recorded as decided on this issue (the marker scheme for fleet-built providers, and the rule that official upstream ids are never renamed).
- A complete rename map (config id, source id, package) for every fleet-built provider is attached to this issue before any rename executes.
- Renames, when executed, land as one coordinated pass across the fork and the fleet config in developing-today/code, with a compat/migration note for stored route-health and session rows keyed by old ids.
Activity
dezren39 commentedon Nov 6, 2026
Addendum — pools-first routing shapes the rename's blast radius (Drew, 2026-11-06 04:00 CST)
Drew's routing principle, stated alongside this design: nearly all usage goes through POOLS (plan routes); direct provider/model seats are the exception, used only where exactly one specific provider+model is deliberately wanted.
What that changes for this design — nothing about the convention itself, but the migration notes should be read with this sizing:
haiku-plan/sonnet-plan/opus-planlead seats namingclaude-code/*,mistral-plan's membership namingvibe-direct, the antigravity seats insidesonnet-plan/opus-plan/gemini-flash-plan/argon-plan), plus the provider blocks themselves anddisabled_providers. Session traffic names the pool, not the provider — so a provider rename touches the pool layer almost exclusively.(A separate lane owns the route→model#effort map and the pools-first audit; this note only records the principle's implication for the rename map.)
dezren39 commentedon Nov 6, 2026
Intake review
🤖 Fleet monitor intake (repo-fleet-monitor), 2026-11-06.
dezren39 commentedon Nov 6, 2026
🤖 Agent note · triaged — design is complete and current; blocked on Drew's ruling (escalated)
dt-prefix (recommended — short, dash-native, unmistakably ours, near-zero collision risk; e.g.claude-code→dt-claude) vsours-(plain-English fallback, same mechanics) vs another marker. Slash namespaces are mechanically impossible (the id is the first segment of everyprovider/modelleaf string); leading_reads as private/hacky;.providersays "is a provider", not "ours".opendesignandcline-passare our config ids but name third-party services (likeopenrouter). Proposal in the body: leave them unchanged; Drew rules whether every fleet-config id gets badged instead.metarename line is scheduled: today configmetabinds the@ai-sdk/openaidoor to api.meta.ai, while the native fork packagemetais a different thing. Renaming before this is decided risks silently rebinding the config door.disabled_providers, route leaves — then deploy + verify viaGET /api/provider); a follow-up implementation task gets enqueued from this issue at that point. Until then the task is blocked on the ruling, not on any engineering unknown.dezren39 commentedon Nov 6, 2026
Alignment record update — muse-direct (2026-11-06)
The muse-direct row of the provider alignment audit is resolved:
muse-directwas an@ai-sdk/openaiconfig block aimed at a loopback proxy (muse-proxy, :18747) that performed the Meta key exchange and Responses translation out-of-process — a proxy wearing a "direct" name.muse-directis a native fork provider package (@opencode/ai/providers/muse-direct, fork PR muse-direct: native Meta wire provider (#1825) #1872) speaking the Meta Responses wire in-process, performing the/muse-code/keyminted-key exchange itself from~/.config/muse/auth.json. No proxy hop, no subprocess, no placeholder key, no config baseURL/apiKey. muse-proxy is stopped, disabled (unit not-found), its port is dead, and its repo definition is removed (code PR feat: Add kotlin lsp integration anomalyco/opencode#6601).muse-direct, modelsmuse-spark-1.3-contributor/muse-wonder-1.0-contributor; the two pinpoint seats (speed head / workhorse-primary leaf on spark#xhigh, summit on wonder#xhigh) never moved. Pool discipline intact:metaremains the only PAYG door under its own id;musestays disabled.dezren39 commentedon Nov 7, 2026
Rulings recorded — Drew, 2026-11-07 07:43 + 07:45 CST
dt-, notours-.Classification — verified from source (git history/authorship in this fork, 2026-11-07)
Custom-built in this fork (adding commit author):
claude-code(Drewry Pope, 2026-11-05),antigravity(Drewry Pope, 2026-11-02),vibe(developing-today[bot], 2026-11-04),commandcode(Drewry Pope, 2026-11-05),muse-direct(Drewry Pope, 2026-11-06; a native source provider since #1872, not config-only).Upstream: everything else in
packages/ai/src/providers/, includingmeta—providers/meta.tswas added by upstream PR anomalyco#47826 ("feat(ai): add Meta provider", Aiden Cline, 2026-09-07) and every later commit on it is by upstream authors; zero fleet commits. This corrects this issue's inventory, which listedmetaas fleet-built. Per the mechanical rule,metagets NO underscore. Flagged for Drew: if the intent was that the fork's Meta door specifically is ours, the fleet-built Meta provider ismuse-direct→_muse; the upstreammetaprovider staysmeta.Config-only doors (no fork provider source; they bind upstream SDK packages
@ai-sdk/openai[-compatible]):opendesign,cline-pass— provider implementation is upstream → no underscore, unchanged. (Same outcome the proposal reached, for the rule's reason: it's about who built the provider, not whose service sits behind it.)Rename map (executed as one coordinated pass)
claude-codeclaude-codeclaude_claudeantigravity-directantigravityantigravity_antigravity(config+source converge)vibe-directvibe_vibe(converge)commandcodecommandcodecommand-code_commandcode(spelling split closed)muse-directmuse-direct_musemetametametaopendesign,cline-passantigravity-ls,antigravity-agyNotes:
providers/claude-code.ts,@opencode/ai/providers/claude-code) are internal module paths, not provider ids — unchanged.commandcode→_commandcode,antigravity-direct.gemini→_antigravity.gemini,antigravity-direct.claude-gpt→_antigravity.claude-gpt— each starts a new snapshot series; pre-rename series stay unrewritten.aggregator/src/provider-display.ts(the dashboard display-name function) and the fork quota CLI's human header; JSON/machine surfaces keep the canonical id.claude-directname in Rename custom provider claude-code -> claude-direct (naming alignment, later) #1817 (the underscore convention replaces the-directscheme).Execution: fork PR + code-repo PR (config + pm-stack), merge commits only, no deploy outside the normal path.
ai+cli: #1823 rename follow-through — disabledBy rationale comment, q…
dezren39 commentedon Nov 7, 2026
Execution record — 2026-11-07
Renames executed per the ruling comment above:
claude-code→_claude,antigravity→_antigravity,vibe→_vibe,commandcode→_commandcode,muse-direct→_muse), quota canonical ids + aliases +disabledBypins, quota CLI display strip. Tests: targeted suites green; full ai suite failures identical to pristine baseline.provider-display.ts). Tests: quota files 147/147, bin tests 47/47, full aggregator failing set identical to baseline.Not renamed:
meta— upstream provider code (anomalyco/opencode anomalyco#47826); flagged in the ruling comment for Drew's confirmation.opendesign/cline-pass— config doors over upstream SDK packages, unchanged per the rule.Tracked follow-ups (not in either PR):
GET /api/providershows the underscored ids;opencode quotaresolves old spellings via aliases.provider-display.ts) and the fork quota CLI header already do.Merge pull request #1944 from developing-today-forks/rename/provider-…
dezren39 commentedon Nov 8, 2026
🤖 Agent note · triaged
status/blockedanduser/escalatedlabels are stale and are removed by this note; the tasks that waited on this ruling (Rename custom provider claude-code -> claude-direct (naming alignment, later) #1817's follow-ups) are unblocked.GET /api/provider;opencode quotaresolving old spellings via aliases) after the next normal deploy. Issue stays OPEN for that verification; follow-ups 2–3 are recorded on the execution comment.