# Gadget Code Workspaces

I want to talk about Project Management in the application, and a bit of a change in philosophy. This can be viewed as maturity for the system, a refinement that has evolved out of use, and the careful consideration of that use.

This session won't involve the socket protocol, or AI API calls. This session will focus on @docs/workspace-management.md and @docs/gadget-workspace.md, and the @gadget-code/src/models/project.ts managed by them.

We are going to revisit @gadget-drone/docs/gadget-drone.md, and specifically the startup procedure.

Now that you have a fairly complete picture of how things are, I want you to please reasona about the following:

1. A drone 'instance' is now used for locking a Workspace. The workspace itself is now assigned an ID (see below), which it can now do using nanoid as used elsewhere throughout the project.
2. When a drone is starting in a workspace directory (one with a .gadget directory populated with the expected contents, intact), it will register as the drone that is currently servicing that workspace. The drone will "lock" the workspace to itself. And this is to prevent other drones from starting in the same directory, and colliding.

That is what makes it obvious that a drone's specific runtime instance is never what matters. The drone 'instance' is not what matters. That only determines if the Workspace is current Available, or not.

## Workspace Philosophy Change

Reference: [Gadget Code Workspace](../gadget-workspace.md)

The new [Workspace](../../gadget-code/src/models/workspace.ts) mode and [IWorkSpace](../../packages/api/src/interfaces/workspace.ts) interface have been created to provide the backing for a workspace instance on a host.

A drone runs in a directory on a host. We need to make sure only one drone is ever running in the same directory on the same host at the same time.

## Workspace Files

In the `.gadget` directory there is a `workspace.json` file. We will now be driving drone startup logic using this file. The drone will do more to maintain this file.

For one, the drone must now maintain the workspace file as it deploys projects to the workspace, removes them from the workspace, and works within them.

The drone will also, at startup, query `gadget-code:backend` for each project it has installed, looking for change that might have happened within each `Project` in the time since the drone was shut down. This lets the drone sense changes such as to the slug - which will then need to become a directory name change.

Here is a current workspace.json file contents:

```json
{
  "workspaceId": "0266f92d-feb8-4875-8d3d-701636d937ab",
  "createdAt": "2026-04-30T23:05:23.789Z",
  "hostname": "mysterymachine",
  "workspaceDir": "/home/rob/workspaces/core-001",
  "chatSession": null,
  "lockedProject": {
    "lockedAt": "2026-05-10T15:07:10.884Z",
    "_id": "ZX3ig5Y2cPIJFY1mzrF11",
    "slug": "test-project"
  },
  "projects": [
    {
      "_id": "ZX3ig5Y2cPIJFY1mzrF11",
      "slug": "test-project",
      "clonedAt": null,
      "lastSyncAt": null
    }
  ],
  "registration": {
    "_id": "uvlB26jV7vlki1jlULFUS",
    "status": "available",
    "registeredAt": "2026-05-10T14:32:30.809Z"
  }
}
```

`workspace.json` is always read at startup. It is always written as change happens, and at shutdown.

## Instructions

1. Create gadget-code/src/services/workspace.ts as the CRUD-style service you'll find for Project in that same directory

### WorkspaceService

Implements the CRUD services needed to support workspaces on hosts, and the drones running within them.

### Workspace API Controller

Route: /api/v1/workspace

Endpoints:

- POST /:workspaceId/lock a drone is requesting the workspace lock
- POST / create a workspace and have an \_id assigned

- GET / fetch a list of workspaces owned by the authenticated User
- GET /:workspaceId fetch a specific workspace by \_id

- PUT /:workspaceId update a workspace by \_id

- DELETE /:workspaceId/lock a drone is releasing the workspace lock
- DELETE /:workspaceId the entire workspace is being deleted
