Get started
Projects, locations and workspaces
What a project is, where it lives, and how a branch gets a working copy of its own.
On this page
- The default location
- How a second machine joins a project
- From a checkout that is already there
- By adding the location and letting the first workspace clone
- The projects folder
- Workspaces
- Workspace slugs across locations
- Work moves through the remote
- Taking a project off a location
- When a machine is removed
- A project that lives nowhere
- Directories with no remote
- A name that belongs to another repository
Three words carry the whole model, and the rest of the documentation uses them the same way everywhere.
- A project is a repository. One repository is one project, however many copies of it there are. The project is what a client is authorized for and what a policy is set on.
- A location is a place the project lives: one of your machines, or Exeora Cloud. A project lives in one or more of them. One that has a repository and loses its last location stays a project, and lives nowhere until it is given a place again.
- A workspace is a branch with a working copy of its own, in one location. On a machine of yours it is a Git worktree. On Exeora Cloud it is a machine of its own, called an instance.
A machine is a computer of yours with the CLI on it. An instance is a machine Exeora Cloud runs for you. Tools behave the same on both, so an agent uses a workspace without caring which kind holds it. What an instance comes with, and the scripts a project runs there, are in Exeora Cloud.
The default location#
One location of a project is the default. A call that names no workspace lands there, in the project root of that location. A call that names a workspace goes to the machine that holds that workspace, wherever it is.
The root of any other location is named main@<location>: main@desktop, main@cloud. It is a working copy like any other, on the machine that holds it, and list_workspaces and exeora workspace list show one for every location that has a copy. main alone stays the root of the default location.
The location a project was first added in starts as the default. Change it from the project's page in the dashboard, with Make default on a location, or from the CLI:
exeora project default api --on desktop exeora project default api --on cloud
Making Exeora Cloud the default asks for an instance for the project root, because that is the only time a call that names no workspace would land on Cloud. See Exeora Cloud.
The dashboard, exeora project list and the list_projects tool all describe a location with the same words:
| State | What it means |
|---|---|
online | The machine is connected and answers calls. |
asleep | Exeora Cloud with nothing running right now. The next call wakes the instance, so it counts as reachable. |
offline | A machine of yours that is off, or where exeora connect is not running. |
not cloned | The machine is a location and holds no copy yet. The first workspace made there clones the repository. |
setting up | The repository is being cloned, or an instance is being made. |
failed | The clone or the instance failed. The reason and what to do about it are shown beside it. |
no instance | Exeora Cloud is the default location and holds no instance for the project root. The next call to the project root makes one. |
removed | The machine was revoked, so nothing there answers. |
How a second machine joins a project#
What makes a checkout on another machine the same project is its remote. Exeora reduces the address to host, owner and name, so an ssh remote and an https remote of the same repository are the same project. There are two ways to add the machine, and they end in the same place.
From a checkout that is already there#
cd ~/code/api exeora project add .
When the remote of that checkout is already a project of your account, the machine joins that project as one more location, and the CLI says so instead of announcing a new project. The machine takes the id, slug and name the project already has, whatever the directory is called. Nothing is cloned and nothing is moved.
Only the top of a checkout says which repository it is. A folder inside a checkout is registered as that folder, a project of its own with no repository, because another machine that cloned the repository would hold something else.
By adding the location and letting the first workspace clone#
exeora project locations add api --on desktop exeora workspace create fix/login --project api --on desktop
The first command can run on any machine signed in to your account, or be done from the project's page with Add location. It clones nothing: it says the project may live on that machine. The first workspace asked for there is what brings the copy. The machine has to be registered and connected for that, because only the machine can clone onto itself.
There is also a shorter form when you are at the second machine: exeora project add owner/repo clones the repository into its projects folder and joins the project in one step.
The projects folder#
Each machine has a projects folder, ~/exeora by default. exeora connect asks for it the first time it runs at a terminal. Read or change it afterwards:
exeora config get projects-root exeora config set projects-root ~/code/exeora exeora config unset projects-root
EXEORA_PROJECTS_ROOT overrides it for one environment.
The first time a workspace is asked for on a machine that holds no copy of the repository, the CLI makes one at <projects-root>/<slug>. If a checkout of the same repository is already at that path, it is adopted as it is. Otherwise the repository is cloned there. The CLI never deletes or overwrites what it finds: a folder at that path that holds something else is refused with a message that names it.
A clone tries three ways of asking, in this order, and stops at the first that works: a short-lived token from Exeora when the project is connected to GitHub, the git credentials of the machine over https, and ssh. None of them can stop to ask for a password, because a machine that serves calls in the background has nobody watching it. The clone is made beside its destination and moved into place at the end, so a clone that fails leaves nothing behind. It is stopped after thirty minutes.
Workspaces on a machine are Git worktrees of that clone. They are kept under workspace-root, a separate folder in the platform's data directory, so the projects folder holds only the checkouts you would open in an editor.
Workspaces#
A workspace is created in the location you name, from any of three places: the dashboard (Add workspace on a project's page, or from Source Control), the CLI, and an agent through the create_workspace tool, which takes the location as where.
exeora workspace create fix/login exeora workspace create fix/login --project api --on desktop exeora workspace create fix/login --project api --on cloud
Without --on the workspace is a worktree on the machine the command runs on. With --on cloud it is an instance, and a project that is not on Exeora Cloud yet is put there on the way. list_workspaces and exeora workspace list --all show every workspace with the location that holds it.
Workspace slugs across locations#
A workspace is named in a call by its slug, which comes from the branch: fix/login becomes fix-login. The same branch can have a working copy in two locations, and both would ask for the same slug. The first keeps it. The second is given the slug with its location behind it, fix-login-desktop or fix-login-cloud, so each can be named and each call reaches the machine that holds what it names.
Two workspaces on the same machine asking for one slug is a real conflict, and it is refused. main is reserved: it is the project root at the default location.
Work moves through the remote#
Nothing copies files between locations. A change made on the laptop reaches the desktop or an instance the way it reaches a colleague: commit and push there, fetch here. A workspace in one location does not see uncommitted work in another, and removing a location does not move what was only there.
Taking a project off a location#
exeora project locations remove api --on desktop
Exeora forgets the location and the workspaces it knew there. On a machine of yours nothing on disk is touched: the checkout and its worktrees stay where they are, no longer served. On Exeora Cloud the instances are what the location is, so they are destroyed, with anything that was never pushed from them.
While the project lives somewhere else as well, the default location cannot be removed until another one is the default.
The only location of a project can be removed when the project has a repository. The project stays, and lives nowhere until it is given a place again. A directory with no remote cannot lose its only location, because nothing could clone it anywhere else: that is removing the project, and it is asked for as such with exeora project remove.
When a machine is removed#
A machine leaves in two steps, from Machines in the dashboard. Revoke closes its connection at once. Delete is offered afterwards and cannot be undone.
While a machine is revoked and not yet deleted, a project that lives somewhere else as well is still reachable through its workspaces in the other locations. A call that names no workspace is refused if the revoked machine was the default location, and the refusal lists where the project still lives. Choose a new default to bring those calls back.
Deleting the machine settles it for every project that lived there:
- A project that lives on another machine stays, and its default moves there. A copy that is ready is preferred to one that is not cloned yet, then a machine of yours to Exeora Cloud, and then the oldest location.
- A repository that lived only on that machine stays, and lives nowhere. It keeps its MCP URL, its policy, its clients and its activity history. The files on the machine are not deleted.
- A directory with no remote that lived only on that machine goes with it, along with its activity history, because nothing could clone it anywhere else. The files on the machine are not deleted.
- A project that is also on Exeora Cloud stays. When Cloud is the only other place it lives, Cloud becomes the default location, in state
no instance. No instance is made at that moment, so the room left in the plan never stops a machine from being deleted. The next call to the project root makes the instance.
A project that lives nowhere#
A project is deleted only by removing it, with exeora project remove or Remove project in the dashboard. Losing its last location does not delete a project that has a repository. It lives nowhere: it is still listed, and it keeps its MCP URL, its policy and its clients.
A project comes to live nowhere in three ways. The last machine that held it was deleted. Its only location was removed. Or the instance of its project root on Exeora Cloud was destroyed while it lived on no machine of yours.
When no location is left, the dashboard and exeora project list show the project as nowhere, and list_projects lists it with no locations. Nothing can serve a call to it, so a call is refused with a message that says it lives nowhere. Give it a place again in any of these ways:
exeora project add .in a checkout of it. The machine joins the project that is already there.exeora project add owner/repoon a machine, which clones the repository into the projects folder and joins the project.exeora project locations add api --on desktop, or Add location on the project's page. The first workspace made there clones the repository.create_workspacewithwhereset tocloud, from an agent. It puts the project on Exeora Cloud.
The first machine given to a project that lives nowhere becomes its default location. A project that is on Exeora Cloud keeps Cloud as its default location, in state no instance. The next call to its project root makes the instance and is answered with EXECUTOR_WAKING: send it again in about a minute. exeora project default api --on cloud and Start instance on the project's page ask for the instance ahead of the call.
Directories with no remote#
A directory that is not the top of a checkout, or a checkout with no remote, is still a project. It has no repository, so there is nothing another location could clone: it stays on the one machine it was added from, and adding a location or putting it on Exeora Cloud is refused with the reason. For the same reason it goes with that machine: its only location cannot be removed, and deleting the machine deletes the project.
To change that, give the checkout a remote and run exeora sync on the machine it lives on. The same command teaches Exeora the repository of projects that were added by a CLI older than 0.18.0, which did not send it.
A name that belongs to another repository#
Registering a directory under a slug that already names a project on another machine, when the two are not checkouts of the same repository, is refused with slug_taken. It used to move the project to the new machine without a word and leave the other one holding nothing. Add the directory under another name with --slug, or remove the other project first.