21 KiB
Project-First Host Model
Context
We have been exploring how Orca should make VMs, remote servers, SSH machines, and future cloud-hosted compute feel first class.
The current implementation direction groups the workspace sidebar by execution host:
Local Mac
Project A
workspace-1
SSH / VM 1
Project A
workspace-2
That model is useful as an operational view, but it makes the machine feel like the outermost user concept. After discussion, the stronger long-term product model is project-first:
Project A
Local Mac
workspace-1
Cloud VM 1
workspace-2
In this model, machines are not separate isolated workspaces. They are places where a project can be available and where a workspace can run.
Reference Findings
Superset
Superset is closest to the desired Orca model.
Its conceptual model is:
Project + Host -> Workspace
Specific details:
- A project is the durable repo concept.
- A host is a registered machine that can run workspaces.
- A workspace stores both
projectIdandhostId. - Workspace creation is explicitly host-targeted: pick a project, pick a host, then create the workspace on that host.
- The schema has a uniqueness rule for a "main" workspace per
(projectId, hostId), which means the same project can be materialized on multiple hosts. - Project setup is host-scoped. A project can be cloned or imported on a specific host.
- The UI can block workspace creation with "Project not set up on this host."
- Project settings have host-aware pieces like project location and worktree location on the selected host.
This maps well to Orca because Orca already thinks in repos/projects, worktrees, tasks, agents, and terminals.
Cmux
Cmux is more workspace/session-first.
Its conceptual model is closer to:
Workspace/session -> local or remote execution context
Specific details:
cmux ssh user@remotecreates a workspace for a remote machine.- Remote/SSH is a property of the workspace/session.
- Browser panes can route through the remote network, so remote
localhostworks naturally. - File explorer follows SSH workspaces and shows the remote root.
- Remote sessions have remote configuration and reconnect/persistence behavior.
- Cmux has project-specific command config, but it does not appear to center a durable "Project is available on hosts X/Y/Z" abstraction.
Cmux is a strong reference for SSH/session polish, but not the best reference for Orca's project/worktree data model.
Recommended Orca Model
The recommended durable model is:
Project -> ProjectHostSetup -> Workspace
Where:
Projectis the durable repo identity.ProjectHostSetupmeans "this project is available on this host at this path, with this setup state and host-specific config."Workspaceis a branch/task/worktree instance of a project on one host.
Potential names for ProjectHostSetup:
ProjectInstallationProjectHostSetupProjectLocationHostProject
ProjectHostSetup is probably the clearest product/data term for now.
Current Orca Model Inventory
Orca currently has pieces of the new model, but they are attached to the wrong concepts for a project-first product.
Repo Is Both Project And Host Setup
Repo currently represents the user's project in the UI, but it also owns
host-local setup fields:
pathworktreeBasePathconnectionIdexecutionHostIdhookSettingsgitUsername- repo-specific source-control overrides
That means two checkouts of the same project on two machines become two repos, even when the user thinks of them as one project.
In the project-first model:
- project identity should move to
Project - host-local checkout information should move to
ProjectHostSetup - compatibility can keep
Repoas a transitional projection for old APIs
Worktree Belongs To Repo Only
Worktree currently stores repoId, and the host is inferred from the owning
repo. This works when "repo" means "checkout on one host", but it is awkward
when one project can exist on several hosts.
In the project-first model, a workspace should know:
projectIdhostId- the selected
projectHostSetupId - the worktree path on that host
The existing repoId can initially point at a compatibility setup id, but the
durable direction should be explicit.
Persistence Stores Repos As The Durable Root
PersistedState currently stores repos: Repo[], projectGroups, and
worktree metadata keyed around repo/worktree ids. Recent multi-host work also
stores per-host session partitions, which is good for runtime ownership, but it
does not create a durable "project is set up on host" record.
The migration should derive:
- one
Projectper existing user-visible project identity - one
ProjectHostSetupper existingRepo - one
Hostfrom local, SSH, runtime, and future cloud targets - existing worktrees attached to the setup derived from their current repo
For a local-only user this should be boring: every existing repo becomes a project with one local setup.
Renderer Store Is Repo-Centric
The renderer store has repo-first actions:
fetchReposaddRepoPathaddReporemoveProjectupdateRepofetchWorktrees(repoId)createWorktree(repoId, ...)
Remote runtime support already chooses a target based on the active runtime or repo owner, but the public shape is still repo-centric. A project-first API needs calls like:
fetchProjectsfetchProjectHostSetups(projectId)setupProjectOnHost(projectId, hostId, ...)createWorkspace({ projectId, hostId, ... })
During migration, these can be implemented as wrappers around the current repo APIs so the change is incremental.
Add Project Means Add A Host-Local Checkout
Local repos:add and SSH repos:addRemote both persist a repo at a concrete
path. That path is the important host-local fact, but the UI labels the result
as a project.
In the new model, the add/setup flows split into three actions:
- create or import a durable project identity
- set up that project on a specific host
- create workspaces from any ready setup
Runtime Ownership Is Already Pointing The Right Way
Terminals, sessions, remote PTYs, browser routing, and runtime RPC already have host-aware pieces. The problem is that host ownership is inferred through repo ownership rather than declared on the workspace/setup model.
The new model should preserve the current runtime routing discipline while making host ownership explicit in the data model.
Data Model Shape
Project
Project-global state:
- id
- display name
- repo identity / provider metadata
- icon/color
- default branch
- Git provider linkage
- project-global settings
Host
Host-global state:
- id
- kind: local, SSH, runtime, cloud VM
- label
- online/health/compatibility status
- platform/capabilities
- host-wide settings
- agent availability
ProjectHostSetup
Host-specific project state:
- project id
- host id
- repo path on that host
- worktree base directory on that host
- setup state: not set up, setting up, ready, error, unsupported
- setup method: imported existing folder, cloned repo, provisioned by cloud
- platform/capability constraints
- host-specific project settings
- optional setup/teardown scripts
Workspace
Workspace state:
- project id
- host id
- project host setup id, if we make that a real id
- branch/worktree name
- worktree path on the host
- task/PR/issue linkage
- agent/terminal/browser resources owned by that host
UX Model
Sidebar
Default sidebar should become project-first:
Project A
feature-login Local Mac
benchmark-fix GPU VM
Project B
auth-refactor Work Linux
When a project has workspaces on multiple hosts, we can optionally show host subgroups:
Project A
Local Mac
feature-login
GPU VM
benchmark-fix
Rules:
- If a project only has one host represented, do not add noisy host nesting.
- If a project has multiple hosts, host subgroups can appear automatically.
- Host should remain available as a filter/view mode.
- The current host-first grouping can survive as an alternate operational view, but should not be the default mental model.
Create Workspace
Workspace creation should ask:
- Which project?
- What branch/task/name?
- Which host should run it?
- If the project is not set up on that host, set it up inline or block with a clear action.
Example:
Create workspace
Project: Orca
Branch: feature/remote-hosts
Run on: GPU VM 1
This project is not set up on GPU VM 1.
[Clone repo to host] [Import existing folder] [Cancel]
Set Up Project On A Host
A project settings page should expose which hosts the project is available on:
Project: Orca
Available on:
Local Mac Ready /Users/me/orca
GPU VM 1 Ready /home/me/orca
Work Linux Not set up [Set up]
Setup methods:
- clone from repo URL into a selected parent directory
- import an existing folder on the host
- future: provision cloud VM and clone automatically
Add New Host / VM
Adding a host should not automatically attach every project to it.
After adding a host, Orca should offer:
New host connected: GPU VM 1
Make projects available here:
[ ] Orca Clone to /home/me/orca
[ ] Backend Import existing folder
[ ] ML Runner Clone to /mnt/work/ml-runner
This is also the natural place for future cloud VM monetization:
- provision host
- choose projects to materialize there
- create workspaces on that host
Edge Cases
Project Exists Only On One Host
This is normal. The project has one ProjectHostSetup.
The UI should not imply every project can run everywhere.
Project Requires Linux Or Beefy Hardware
This is also normal. The project can mark local Mac as unsupported or simply not set up. Create-workspace host choices should only show valid hosts by default, with an affordance to reveal unavailable hosts and why they are unavailable.
Work Projects Versus Personal Projects
Do not solve this with host grouping alone. This is better represented by:
- project ownership/account
- project tags/groups
- host availability
- workspace filters
Existing Project On Computer A, Add To Computer B
Use "Set up project on host":
- clone from remote into a host path, or
- import an existing folder on the host.
Add VM And Initialize Many Projects
Use a bulk "Make projects available on this host" flow. Each selected project still needs a per-host location/method.
What Needs To Change
This is a large model change. It is not just a sidebar reorder.
At a high level, 12 areas need to change.
1. Data Model
Add a first-class project-host setup record.
Current host ownership is mostly attached to repos/workspaces through execution-host IDs. The new model needs a durable record for "project X is available on host Y at path Z."
Concrete changes:
- add
Project - add
ProjectHostSetup - decide whether existing
Repobecomes a compatibility projection, a renamed setup type, or is gradually replaced - add selectors that answer "which setups exist for this project?" and "which host owns this workspace?"
2. Persistence And Migration
Existing repos/worktrees need to migrate into:
- project records
- host records
- project-host setup records
- workspace records tied to both project and host
For current local-only users, migration should feel invisible: each project gets a local-host setup.
Concrete changes:
- bump schema version
- migrate every existing
Repointo aProjectplus oneProjectHostSetup - preserve old repo ids or create an alias map so worktree metadata, terminal panes, caches, hooks, automations, and settings do not lose references
- keep downgrade behavior in mind because current persisted state is read by older builds
3. Sidebar Row Model
The sidebar should group primarily by project, not host.
Host grouping becomes nested under projects only when helpful, or becomes a filter/view option.
Concrete changes:
- build sidebar rows from projects, setups, hosts, and workspaces
- show host labels inline for mixed-host projects without adding unnecessary nesting
- keep the host-first view/filter as an operational mode if it remains useful
- revisit drag/reorder so project order, host order within a project, and workspace order remain understandable
4. Workspace Creation
Create workspace needs a host picker that is constrained by project setup.
If the selected host does not have the project, the flow needs setup actions instead of silently failing or creating an ambiguous remote workspace.
Concrete changes:
- change creation input from
repoIdto{ projectId, hostId } - list ready setups first and unavailable hosts with clear reasons
- inline setup/import/clone when a project is not available on the chosen host
- ensure created workspaces persist explicit host/setup ownership
5. Project Setup / Add Project
Adding a project must distinguish:
- create a new project identity
- set up that project on this host
- set up an existing project on another host
This likely replaces a single "add repo" flow with a project-first setup flow.
Concrete changes:
- add "Set up on this host" flows for local paths, SSH paths, runtime hosts, and future cloud VMs
- support clone and import-existing-folder
- support bulk setup when a new host is added
- keep current add-repo flows as compatibility entry points during migration
6. Project Settings
Project settings need a host selector or host table for host-specific settings:
- repo location
- worktree base dir
- setup scripts
- branch prefix
- platform/capability notes
Project-global settings remain global.
Concrete changes:
- split settings into project-global and host-specific sections
- use a host dropdown/table for location, worktree base path, setup scripts, and platform constraints
- keep source-control and review settings provider-aware, not GitHub-only
- make the "which host am I editing?" answer explicit on every host-specific settings pane
7. Host Settings
Host settings remain host-global:
- connection details
- server version/compatibility
- default worktree directory
- agents available on that host
- platform/capabilities
They should not become a separate copy of all project settings.
Concrete changes:
- expose host connection, health, version, platform, and capabilities
- include compatibility warnings for mismatched client/server versions
- keep host-global defaults separate from per-project setup overrides
8. Runtime Ownership
Terminals, browser panes, agents, PTYs, filesystem operations, and setup scripts must route through the workspace's host.
The UI can show project-first organization, but execution still happens on the owning host.
Concrete changes:
- derive runtime target from workspace/setup host, not active sidebar grouping
- keep local, SSH, runtime, and future cloud execution behind the same routing contract
- audit filesystem, git, terminal, browser, agent, hook, and automation paths for repo-id assumptions
9. Compatibility And Availability
Workspace creation must handle:
- host offline
- project not set up
- host version too old
- client version too old
- unsupported platform
- missing agent on selected host
This should be surfaced before creation where possible.
Concrete changes:
- add capability/version probing to host records
- gate project setup and workspace creation on host readiness
- define behavior for new client/old server and old client/new server
- keep unsupported actions disabled with a specific reason
10. CLI / API
CLI and API commands need to accept the project-first model:
orca project setup --project <id> --host <id> --clone ...
orca workspace create --project <id> --host <id> --branch ...
orca project hosts list <project-id>
Existing commands should keep compatibility aliases where possible.
Concrete changes:
- add project/setup/workspace commands that take host explicitly
- keep old repo/worktree commands working as aliases where possible
- return structured availability errors instead of generic failures
11. Caches, Metadata, And Request Ownership
Caches and request ownership need to follow the same identity split.
Project-global caches can stay project keyed. Host-local caches must include the host/setup key because two machines can have different refs, branches, worktree paths, installed agents, filesystem state, and server capabilities for the same project.
Concrete changes:
- decide which caches are project-global versus host/setup-local
- include host/setup ids in branch, worktree, status, filesystem, terminal, and remote capability cache keys
- keep request cancellation scoped to the host that owns the operation
12. Tests And Validation
The validation surface is broad because this changes identity, persistence, runtime routing, and UI organization.
Concrete changes:
- migration tests for local, SSH, runtime, duplicate project-on-two-hosts, and missing/offline hosts
- selector tests for project/setup/workspace grouping
- workspace creation tests for ready, not set up, offline, incompatible, and unsupported hosts
- sidebar tests for single-host projects, mixed-host projects, host filters, and drag/reorder
- SSH end-to-end validation for remote setup and remote workspace creation
- Electron UI verification for the create-workspace and settings flows
Implementation Scale
This is probably not a small patch.
Estimated change categories: 12 meaningful surfaces.
- shared types and persistence
- migration logic
- main-process project/host setup APIs
- renderer store normalization/selectors
- sidebar grouping and drag/reorder behavior
- create workspace flow
- add/setup project flow
- project settings
- host settings
- runtime routing/guards
- CLI/API updates
- tests and compatibility coverage
So the answer is: about 12 meaningful product/engineering surfaces need to change, with the data model, migration, creation/setup flows, and runtime routing being the most important and highest-risk pieces.
Suggested Implementation Sequence
This should be implemented as an additive migration, not a big-bang rename.
- Add project/setup types, selectors, and compatibility helpers while keeping
existing
RepoAPIs alive. - Add persistence migration that derives one setup per existing repo.
- Update store selectors so the sidebar and creation flows can read project-first data without requiring every backend call to change at once.
- Update workspace creation to accept project plus host, then map through the selected setup to current worktree creation internals.
- Add setup-on-host flows for local and SSH paths.
- Split settings into project-global and host-specific sections with an explicit host selector.
- Move sidebar default grouping to project-first while preserving host filters and host-first operational mode if we still want it.
- Audit runtime routing and caches so every host-local operation is keyed by setup/host, not only project.
- Add CLI/API compatibility commands.
- Run migration, unit, SSH, and Electron validation before calling it done.
Implementation Status
Landed so far:
- Added shared
ProjectandProjectHostSetuptypes. - Added a pure compatibility projection from existing
Repo[]into project-firstProject[]andProjectHostSetup[]. - Added renderer store selectors that expose the projected model without duplicating derived state in Zustand.
- Added persisted
projectsandprojectHostSetupscompatibility fields that are backfilled from existing repos on load and kept in sync when repos are added, updated, reordered, or removed. - Exposed read-only project/setup list APIs through local IPC, preload, and runtime RPC so newer clients can ask local or remote servers for the project-first compatibility model.
- Hydrated renderer store
projectsandprojectHostSetupsalongside repos, with a repo-derived fallback for older preloads/runtimes that do not yet implement the project APIs. - Updated the sidebar
groupBy: reporow builder to group by durable project identity when project/setup data exists, while keeping a repo-by-repo fallback for projects that have not been linked across hosts. - Added tests for local repos, SSH repos, same-provider multi-host grouping, no-identity same-name non-grouping, selector cache behavior, persistence backfill, repo mutation synchronization, renderer hydration, and runtime RPC routing. Sidebar row-builder tests now cover project-first multi-host grouping and same-name repo separation without project identity.
Important limitation:
- This is not the full migration yet.
Reporemains the source of truth for the compatibility records, and create-workspace/settings/sidebar flows still use the current repo-centric APIs until the later steps above are implemented.
Recommendation
Use the current host-first sidebar work as a useful transitional and optional operational view.
For the long-term Orca model, move to project-first:
Project -> ProjectHostSetup -> Workspace
This gives us:
- a less jarring experience for local-only users
- clean support for SSH machines and VMs
- clear handling for project exclusivity
- a natural future cloud VM monetization path
- a better fit for repo/worktree/task/agent workflows