The project manifest

The project manifest, a write-once file of defaults the editors read on load.

project.json sits at the root of every project. It records the project's name and description and names the workflow and world the Workflow Editor should preselect.

The important thing to understand about this file: it is written once and then only read. The scaffold that creates your project writes it, and nothing writes it again. The platform reads it for defaults and never updates it. The gateway's manifest reader is explicitly read-only.

That has a consequence worth internalizing before you go looking for a bug: the authoritative record of your project's name, description, and archived state lives in the cloud database, not in this file. Renaming or archiving a project updates that record and leaves project.json untouched.

Example

{
  "name": "plate-prep",
  "description": "Plate preparation runs.",
  "created_at": "2026-05-16T02:52:57.244Z",
  "updated_at": "2026-05-16T02:52:57.244Z",
  "archived": false,
  "active_workflow": "plate_prep_v2",
  "active_world": "bench_layout"
}

Note that created_at and updated_at are identical. They will stay identical for the life of the project, because nothing rewrites the file.

Fields

The scaffold writes exactly these seven keys.

FieldTypeDescription
namestringThe project's display name. 1–128 characters; must be unique among your projects.
descriptionstringFree-text description. May be empty.
created_atstring (RFC 3339 with milliseconds)When the scaffold ran.
updated_atstring (RFC 3339 with milliseconds)Set to the same value as created_at and never changed.
archivedbooleanWritten as false and never flipped. Archive state is tracked in the cloud record, not here.
active_workflowstring | nullThe workflow_id (filename without .json) the Workflow Editor preselects. null if none.
active_worldstring | nullThe world id (folder name under worlds/) the Workflow Editor and the Skills Editor preselect. null if none.

name carries no character-set restriction, only a 1–128 character length bound. Hyphens are fine. This is a looser rule than the one for skills, workflows, worlds, and objects, whose names must match ^[a-z_][a-z0-9_-]{0,63}$.

How active_workflow and active_world resolve

Both are validated when read, not when written. The gateway checks that workflows/<active_workflow>.json is a file and that worlds/<active_world>/ is a directory. If either is missing, it returns no default and the editor falls back to the first item in the list.

It does not repair the file. A stale active_workflow naming a workflow you deleted stays in project.json indefinitely and is ignored on every read. Nothing breaks, and nothing cleans it up.

The editors treat these as the middle tier of a three-step preference: an explicit choice you navigated with wins, then the project.json default, then the first item in the list. A navigated choice only wins if it still exists in the list, so a selection carried over from another project cannot mask this project's own default.

The Skills Editor honours active_world too. Earlier builds ignored it there and always took the first world in the list, so a project whose default was set deliberately still opened on the wrong one.

📝

Opening a different workflow or world does not rewrite active_workflow or active_world. There is no write path for these fields anywhere in the app, the IDE, or the CLI. If you want to change the preselected default, edit this file by hand and commit it.

What updates the cloud record instead

These commands change the project record in the cloud. None of them touch project.json.

ActionWhat it changes
zeon project rename <project> <new-name>The cloud record's name. <project> is the project id or its current name.
zeon project archive <project>Sets archived_at on the cloud record, which hides the project from the default list.

The cloud record also holds a project_id, the project's real identity. The name in this file is a display label; the id is what the sync service actually keys on.

Because the record and the file are separate, they can disagree. After zeon project rename, the cloud knows the new name and project.json still has the old one. That is expected, and nothing reconciles them.

Editing it by hand

This is the normal way to change any of these values, and it is safe. Treat it as an ordinary JSON edit: change the file, then commit and push it like any other file.

The common edits are repointing active_workflow or active_world, or setting them to null for a clean slate.

description is not read back at all. name is read in one place that is easy to miss: data export uses it as the project segment of every exported run's key, falling back to the project id when the manifest has no name. Editing name by hand therefore silently changes where a project's exported data lands. Use zeon project rename <project> <new-name> to change the name you actually see.

When the file is wrong

If project.json is missing or contains malformed JSON, the gateway treats it as an empty manifest: no configured defaults, and the editors fall back to first-in-list. It fails quietly rather than blocking you from opening the project.

See also


Did this page help you?