You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I searched existing issues and did not find a duplicate.
I am describing a concrete problem or use case, not just a vague idea.
Area
apps/web
Problem or use case
My projects live in two trees that mean different things:
~/Developer/Personal/...
~/Developer/Work/...
Everything under Work should start on my work provider account and its approved model. Everything under Personal should start on my personal one. The split is a property of where the project lives, not of any individual project.
Today the default provider and model is a per-project field. defaultModelSelection already exists on the project record (packages/contracts/src/orchestration.ts:225, :424, :1086), project.meta.update accepts it (:629, :639), and draft/thread creation already consumes it. So the mechanism works — but it has to be set once per project, by hand, and again for every new project I add.
That does not scale past a handful of repos, and the failure mode is quiet: a new project under Work inherits nothing, so the first thread starts on whichever selection was last used, which may be the personal account. The mistake is usually only obvious after the turn has already run.
Proposed solution
Let a parent directory carry a default ModelSelection that projects underneath inherit.
In sidebar/project settings, allow setting a default provider + model on a directory scope (e.g. ~/Developer/Work), not just on a single project.
Resolve a project's effective default by walking its workspaceRoot up to the nearest ancestor that has a default configured; the longest matching path prefix wins, so ~/Developer/Work/client-a can still override ~/Developer/Work.
An explicit per-project defaultModelSelection continues to win over any inherited one.
New threads and drafts consume the resolved value through the path that already exists — no change to thread creation.
Path prefix matching already has a home: normalizeProjectPathForComparison and the ancestor/prefix logic in packages/client-runtime/src/state/projectGrouping.ts do this kind of comparison for the sidebar's directory grouping today.
Why this matters
It turns "keep work and personal accounts separate" from a per-project chore that silently fails on every new repo into a rule I state once. That matters for cost attribution, for subscription and rate limits landing on the right account, and for organizational boundaries where running a work repo through a personal account is a real problem rather than an inconvenience.
It is also the natural way to express the intent. I do not want to configure thirty projects; I want to say "this tree is work".
Smallest useful scope
One inherited ModelSelection per directory, resolved by longest matching path prefix, with per-project settings taking precedence.
No new grouping entity, no per-folder settings UI tree, no allow-list of permitted models, no server or provider changes. Reuse the existing defaultModelSelection contract and the existing project-settings dialog; add the directory scope and the resolution step.
Alternatives considered
Set it per project — what I do now. It works, but every new repo starts wrong until I notice, which is exactly the case I want to eliminate.
Resolution needs one clear rule. Longest matching prefix, project override wins, is the least surprising; anything fuzzier gets hard to reason about when trees nest.
Path comparison has to stay consistent with existing normalisation — case sensitivity, trailing separators, and Windows separators. normalizeProjectPathForComparison already handles this and should be the single source of truth rather than a second implementation.
Symlinked or moved projects can fall outside the tree they appear to be in. Matching on the stored workspaceRoot is predictable even if it occasionally surprises.
The UI needs to show why a project's default is what it is — an inherited value that looks unset is worse than no feature. Showing "inherited from ~/Developer/Work" alongside the control would cover it.
Examples or references
Relevant existing surface:
defaultModelSelection on the project record — packages/contracts/src/orchestration.ts:225, :424, :1086
project.meta.update accepting it — packages/contracts/src/orchestration.ts:629, :639
Path normalisation and ancestor matching — packages/client-runtime/src/state/projectGrouping.ts
This discussion was converted from issue #6179 on August 15, 2026 09:52.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Before submitting
Area
apps/web
Problem or use case
My projects live in two trees that mean different things:
Everything under
Workshould start on my work provider account and its approved model. Everything underPersonalshould start on my personal one. The split is a property of where the project lives, not of any individual project.Today the default provider and model is a per-project field.
defaultModelSelectionalready exists on the project record (packages/contracts/src/orchestration.ts:225,:424,:1086),project.meta.updateaccepts it (:629,:639), and draft/thread creation already consumes it. So the mechanism works — but it has to be set once per project, by hand, and again for every new project I add.That does not scale past a handful of repos, and the failure mode is quiet: a new project under
Workinherits nothing, so the first thread starts on whichever selection was last used, which may be the personal account. The mistake is usually only obvious after the turn has already run.Proposed solution
Let a parent directory carry a default
ModelSelectionthat projects underneath inherit.~/Developer/Work), not just on a single project.workspaceRootup to the nearest ancestor that has a default configured; the longest matching path prefix wins, so~/Developer/Work/client-acan still override~/Developer/Work.defaultModelSelectioncontinues to win over any inherited one.Path prefix matching already has a home:
normalizeProjectPathForComparisonand the ancestor/prefix logic inpackages/client-runtime/src/state/projectGrouping.tsdo this kind of comparison for the sidebar's directory grouping today.Why this matters
It turns "keep work and personal accounts separate" from a per-project chore that silently fails on every new repo into a rule I state once. That matters for cost attribution, for subscription and rate limits landing on the right account, and for organizational boundaries where running a work repo through a personal account is a real problem rather than an inconvenience.
It is also the natural way to express the intent. I do not want to configure thirty projects; I want to say "this tree is work".
Smallest useful scope
One inherited
ModelSelectionper directory, resolved by longest matching path prefix, with per-project settings taking precedence.No new grouping entity, no per-folder settings UI tree, no allow-list of permitted models, no server or provider changes. Reuse the existing
defaultModelSelectioncontract and the existing project-settings dialog; add the directory scope and the resolution step.Alternatives considered
Risks or tradeoffs
normalizeProjectPathForComparisonalready handles this and should be the single source of truth rather than a second implementation.workspaceRootis predictable even if it occasionally surprises.Examples or references
Relevant existing surface:
defaultModelSelectionon the project record —packages/contracts/src/orchestration.ts:225,:424,:1086project.meta.updateaccepting it —packages/contracts/src/orchestration.ts:629,:639packages/client-runtime/src/state/projectGrouping.tsContribution
All reactions