Context
OpenKhodam currently consumes OpenCode models only after a provider is already connected. The current flow is:
Chat UI -> useOpenCodeModels -> client.provider.list({ directory }) -> connected providers only -> model picker -> session.promptAsync/create
This means users have no OpenKhodam-native path to connect a provider, understand disconnected providers, or recover when no connected model exists.
OpenCode already has a generic provider/auth system that tells the app which providers exist and how each provider authenticates. We should build OpenKhodam's provider UX on top of that instead of implementing provider-specific auth ourselves.
Important OpenCode reference behavior
OpenCode desktop uses:
client.provider.list({ directory })
- returns all available providers
- returns connected provider IDs
- returns default model IDs
client.provider.auth()
- returns auth methods per provider
- methods can be
api or oauth
- methods can include extra prompts
client.auth.set({ providerID, auth })
- stores API-key auth in OpenCode
client.provider.oauth.authorize(...)
client.provider.oauth.callback(...)
client.auth.remove({ providerID })
- disconnects provider auth
client.global.dispose()
- refreshes runtime/provider state after auth changes
Relevant OpenCode files:
packages/app/src/components/settings-providers.tsx
packages/app/src/components/dialog-connect-provider.tsx
packages/app/src/components/dialog-select-provider.tsx
packages/app/src/components/dialog-select-model.tsx
packages/app/src/hooks/use-providers.ts
packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts
packages/opencode/src/provider/auth.ts
Local OpenKhodam files to inspect
packages/desktop/src/renderer/src/hooks/useOpenCodeModels.ts
packages/desktop/src/renderer/src/hooks/opencode/client.tsx
packages/desktop/src/renderer/src/pages/SettingsPage.tsx
packages/desktop/src/renderer/src/components/chat/ChatHomePage.tsx
packages/desktop/src/renderer/src/hooks/useOpenCodeChatInterface.ts
packages/desktop/src/renderer/src/hooks/useOpenCodeChat.ts
Direction
OpenKhodam should own the desktop UX around providers.
OpenCode should remain the source of truth for:
- provider catalog
- auth method schema
- OAuth/API-key storage
- connected state
- available models
OpenKhodam should not build a parallel credential store.
MVP 1: Provider visibility and connection entry points
Goal
Users can see provider status and have an obvious path to connect a provider.
Build
- Add a Providers section to Settings.
- Show connected providers.
- Show popular disconnected providers.
- Add "View all providers" / searchable provider list.
- Use OpenCode provider catalog, not hardcoded provider details.
Suggested popular providers:
- OpenCode
- Anthropic
- OpenAI
- Google
- OpenRouter
- GitHub Copilot
- Vercel
Calls
client.provider.list({ directory })
client.provider.auth()
Acceptance criteria
- Settings shows connected providers.
- Settings shows popular disconnected providers.
- User can open a provider connect flow.
- If no models are connected, chat/model picker points user toward connecting a provider.
MVP 2: Generic connect/disconnect flow
Goal
Users can connect providers without OpenKhodam implementing provider-specific logic.
Build
Create a generic provider connect dialog driven by OpenCode auth methods.
Auth method shape:
type ProviderAuthMethod = {
type: 'api' | 'oauth'
label: string
prompts?: Array<
| { type: 'text'; key: string; message: string; placeholder?: string }
| { type: 'select'; key: string; message: string; options: Array<{ label: string; value: string }> }
>
}
Flow:
- Load auth methods with
client.provider.auth().
- If one method exists, auto-select it.
- If multiple methods exist, show method picker.
- If method is
api, show API key input.
- If method has prompts, render prompts generically.
- If method is
oauth, call authorize, open returned URL, then call callback.
- After success, call
client.global.dispose() and invalidate provider/model queries.
Calls
API key:
client.auth.set({
providerID,
auth: {
type: 'api',
key,
metadata: promptInputs
}
})
OAuth:
client.provider.oauth.authorize({
providerID,
method,
inputs
})
client.provider.oauth.callback({
providerID,
method,
code
})
Disconnect:
client.auth.remove({ providerID })
client.global.dispose()
Acceptance criteria
- API-key providers can be connected.
- OAuth providers can be connected if OpenCode exposes OAuth methods.
- Providers with extra prompt fields can be handled generically.
- Connected provider models appear after refresh.
- Disconnect removes the provider from connected state.
- No provider secret is stored in OpenKhodam project/session artifacts.
MVP 3: Model picker integration
Goal
The chat model picker should guide users through provider setup instead of only showing connected models.
Build
- Keep showing connected models as selectable.
- Add "Connect provider" action in the model picker.
- If no connected models exist, show an empty state with connect CTA.
- After connecting, refresh model list and allow selection.
Current path:
ChatPromptComposer -> ModelPickerCombobox -> useOpenCodeModels -> prompt model
Desired path:
ChatPromptComposer -> ModelPickerCombobox -> ConnectProviderDialog -> OpenCode auth -> refresh models -> select model -> prompt
Acceptance criteria
- User can connect a provider from the chat/model picker path.
- Chat send remains blocked until a connected model is selected.
- Helper text explains missing provider/model state.
- Prompt submission still sends:
model: {
providerID,
modelID
}
MVP 4: Local default provider/model selection
Goal
OpenKhodam remembers the user's last selected model.
Build
- Persist last selected provider/model locally.
- Resolve selection in this order:
- current explicit selection
- saved local selection if still connected
- OpenCode default model
- first connected model
Acceptance criteria
- User does not need to reselect model every time.
- If saved provider disconnects, UI falls back safely.
- No secret material is persisted.
Maturity 1: Project/session-level defaults
Goal
Users can have provider/model defaults per project or session.
Build
- Add project-level default provider/model.
- Optionally snapshot selected provider/model when creating a session.
- Selection resolution becomes:
- session selected/snapshotted model
- project default
- app default
- OpenCode default
- first connected model
Acceptance criteria
- Project default affects new sessions in that project.
- Existing sessions do not unexpectedly change unless explicitly selected.
- Disconnected project default shows a recoverable warning.
Maturity 2: Provider management polish
Goal
Provider setup feels like a first-class part of OpenKhodam.
Build
- Better provider cards:
- connected source: api/oauth/env/config/custom if available
- provider notes
- recommended badges
- environment-managed providers cannot be disconnected from UI
- Search all OpenCode providers.
- Support custom provider only if we intentionally decide to expose OpenCode's custom provider flow.
Acceptance criteria
- Users can understand why a provider is connected.
- Users can distinguish app-managed vs environment/config-managed providers.
- Provider list scales beyond popular providers.
Maturity 3: Robust auth/callback handling
Goal
OAuth/API-key flows are reliable in desktop contexts.
Build
- Handle OAuth code vs auto callback methods.
- Open auth URLs through Electron shell.
- Surface provider auth errors clearly.
- Ensure query invalidation and sidecar refresh happen after auth changes.
- Consider deep-link callback support only if OpenCode/provider flow requires it.
Acceptance criteria
- OAuth failure shows actionable error.
- Auth cancellation does not leave stale pending UI.
- Successful auth refreshes connected provider/model state.
Explicit non-goals
- Do not build OpenKhodam's own provider credential store.
- Do not hardcode Anthropic/OpenAI/Google-specific auth behavior.
- Do not store provider secrets in project artifacts, session memory, or renderer durable state.
- Do not implement custom providers in MVP unless required by product scope.
Testing
Use repo commands through Nix:
nix develop -c pnpm lint
nix develop -c pnpm typecheck
Add focused tests where feasible:
- provider list normalization
- connected vs disconnected provider display
- auth method rendering:
- model picker empty state
- model picker connect CTA
- selected model fallback when provider disconnects
If e2e provider auth is difficult, use fixture-backed provider API responses for e2e and cover actual auth method handling with lower-level tests.
Review focus
- Reuse OpenCode provider/auth APIs instead of duplicating provider logic.
- Keep provider secrets out of OpenKhodam-owned project/session storage.
- Keep code footprint small in MVP: hooks + settings section + generic dialog.
- Make model picker recovery path obvious when no connected provider exists.
- Preserve existing prompt send flow through
providerID/modelID.
Context
OpenKhodam currently consumes OpenCode models only after a provider is already connected. The current flow is:
Chat UI -> useOpenCodeModels -> client.provider.list({ directory }) -> connected providers only -> model picker -> session.promptAsync/createThis means users have no OpenKhodam-native path to connect a provider, understand disconnected providers, or recover when no connected model exists.
OpenCode already has a generic provider/auth system that tells the app which providers exist and how each provider authenticates. We should build OpenKhodam's provider UX on top of that instead of implementing provider-specific auth ourselves.
Important OpenCode reference behavior
OpenCode desktop uses:
client.provider.list({ directory })client.provider.auth()apioroauthclient.auth.set({ providerID, auth })client.provider.oauth.authorize(...)client.provider.oauth.callback(...)client.auth.remove({ providerID })client.global.dispose()Relevant OpenCode files:
packages/app/src/components/settings-providers.tsxpackages/app/src/components/dialog-connect-provider.tsxpackages/app/src/components/dialog-select-provider.tsxpackages/app/src/components/dialog-select-model.tsxpackages/app/src/hooks/use-providers.tspackages/opencode/src/server/routes/instance/httpapi/handlers/provider.tspackages/opencode/src/provider/auth.tsLocal OpenKhodam files to inspect
packages/desktop/src/renderer/src/hooks/useOpenCodeModels.tspackages/desktop/src/renderer/src/hooks/opencode/client.tsxpackages/desktop/src/renderer/src/pages/SettingsPage.tsxpackages/desktop/src/renderer/src/components/chat/ChatHomePage.tsxpackages/desktop/src/renderer/src/hooks/useOpenCodeChatInterface.tspackages/desktop/src/renderer/src/hooks/useOpenCodeChat.tsDirection
OpenKhodam should own the desktop UX around providers.
OpenCode should remain the source of truth for:
OpenKhodam should not build a parallel credential store.
MVP 1: Provider visibility and connection entry points
Goal
Users can see provider status and have an obvious path to connect a provider.
Build
Suggested popular providers:
Calls
Acceptance criteria
MVP 2: Generic connect/disconnect flow
Goal
Users can connect providers without OpenKhodam implementing provider-specific logic.
Build
Create a generic provider connect dialog driven by OpenCode auth methods.
Auth method shape:
Flow:
client.provider.auth().api, show API key input.oauth, call authorize, open returned URL, then call callback.client.global.dispose()and invalidate provider/model queries.Calls
API key:
OAuth:
Disconnect:
Acceptance criteria
MVP 3: Model picker integration
Goal
The chat model picker should guide users through provider setup instead of only showing connected models.
Build
Current path:
ChatPromptComposer -> ModelPickerCombobox -> useOpenCodeModels -> prompt modelDesired path:
ChatPromptComposer -> ModelPickerCombobox -> ConnectProviderDialog -> OpenCode auth -> refresh models -> select model -> promptAcceptance criteria
MVP 4: Local default provider/model selection
Goal
OpenKhodam remembers the user's last selected model.
Build
Acceptance criteria
Maturity 1: Project/session-level defaults
Goal
Users can have provider/model defaults per project or session.
Build
Acceptance criteria
Maturity 2: Provider management polish
Goal
Provider setup feels like a first-class part of OpenKhodam.
Build
Acceptance criteria
Maturity 3: Robust auth/callback handling
Goal
OAuth/API-key flows are reliable in desktop contexts.
Build
Acceptance criteria
Explicit non-goals
Testing
Use repo commands through Nix:
Add focused tests where feasible:
If e2e provider auth is difficult, use fixture-backed provider API responses for e2e and cover actual auth method handling with lower-level tests.
Review focus
providerID/modelID.