Schema Editing

Added in version vNext.

Reads and changes schemas (document types) and their properties, one small command per change: rename a property, add a field, change a type, edit pick list options.

These commands are built for agents and scripts. People editing schemas by hand should use the schema editor in the UI.

Commands

All commands take --dataBase (file path or remote URL) and --credentials (for remote sources). Every write takes --dryRun, which validates and prints the same summary without writing.

Command

Parameters

MCP tool

DATA SCHEMA GET

--schema, --details

schema_get

DATA SCHEMA CREATE

--name, --schemaType, --idGenerator, --displayName, --description, --group, --icon

schema_create

DATA SCHEMA RENAME

--schema, --newName

schema_rename

DATA SCHEMA UPDATE

--schema, --displayName, --description, --schemaType, --idGenerator, --group, --icon

schema_update

DATA SCHEMA DELETE

--schema, --allowDataLoss, --cascade Deny|Cascade

schema_delete

DATA SCHEMA PROPERTY GET

--schema, --property, --details

schema_property_get

DATA SCHEMA PROPERTY ADD

--schema, --name, --type, --requirement, --uniqueness, --default, --after, --displayName, --description

schema_property_add

DATA SCHEMA PROPERTY RENAME

--schema, --property, --newName

schema_property_rename

DATA SCHEMA PROPERTY UPDATE

--schema, --property, --requirement, --uniqueness, --default, --after, --displayName, --description

schema_property_update

DATA SCHEMA PROPERTY UPDATESPECIFICATION

--schema, --property, --specification, --preservePickList, --preserveFormula

schema_property_update_specification

DATA SCHEMA PROPERTY UPDATEPICKLIST

--schema, --property, --changes, --allowDataLoss

schema_property_update_picklist

DATA SCHEMA PROPERTY CHANGETYPE

--schema, --property, --type, --default, --allowDataLoss

schema_property_change_type

DATA SCHEMA PROPERTY REMOVE

--schema, --property, --allowDataLoss

schema_property_remove

Option values and defaults:

  • --schemaType (CREATE, UPDATE): Normal (default), Component (always embedded in other documents), Settings (one document only) or Union.

  • --idGenerator (CREATE, UPDATE): how the Id of new documents is produced. None (default, you supply every Id), ObjectId, Guid, Sequence (per schema) or GlobalSequence (across the project).

  • --cascade (DELETE): what happens to properties of other schemas that reference or embed the deleted schema, including shared properties. Deny (default) refuses the delete and lists them; Cascade removes them along with the schema.

  • --allowDataLoss: needed only when the edited schema has documents (embedded ones included). On an empty schema every command runs without it.

  • --requirement: None (default), NotNull or NotEmpty. --uniqueness: None (default), Unique or UniqueInCollection.

Rules shared by all commands:

  • --schema and --property take exact names or Ids. GET, ADD, UPDATE, CHANGETYPE and REMOVE accept a space-separated list (--schema Quest QuestStep) or '*' alone for all. Other commands take exactly one. On writes '*' skips the Id property; on GET it lists it too. Schema '*' never selects the system schemas (Schema, SchemaProperty, ProjectSettings).

  • There are no patterns: Quest* is an unknown name, and ! exclusions are not supported. Every listed name must exist, otherwise nothing is written and the error names the missing ones.

  • Quote '*': a bare * is expanded to file names by the shell before Charon sees it.

  • The Id property cannot be renamed, removed or moved.

  • Unknown options fail these commands (--dry-run instead of --dryRun is an error, not a silent real write). Other DATA commands keep ignoring unknown options.

  • Write output is a short summary: targets, changes, affected document count and warnings. Errors go to stderr with exit code 2.

Type Grammar

--type takes one quoted string <DataType> [size] [schema] [options]. GET prints types in the same form, so a printed type passed back to CHANGETYPE changes nothing.

Form

Meaning

Text, Text 100, LocalizedText 500

optional maximum length

Logical, Date, Time

no arguments

Integer 4, Number 8

size in bytes, 1-8; omitted size is 4

Reference Item, ReferenceCollection Item

referenced schema name, required

Document Quest, DocumentCollection Reward

embedded schema name, required

ReferenceCollection 10 Item, DocumentCollection 10 Reward

optional maximum item count before the schema name

PickList Common=0 Rare=1 Epic=2

options; omitted values are assigned 0, 1, 2…

MultiPickList Fire=1 Ice=2 Poison=4

options; omitted values are assigned as powers of two

The type fully determines size and reference target: Integer 8 changed to Text becomes an unlimited Text, not Text 8. Formula is not supported by the grammar.

Pick List Changes

UPDATEPICKLIST edits options partially. Put all changes in one quoted --changes value; unquoted, the shell would split them.

Token

Meaning

+Name=value

add an option

+Name

add with the next free value (next free power of two for MultiPickList)

-Name

remove by name

-Name=value

remove and assert the current value; fails when it differs (stale view guard)

Removals apply before additions. A removal and an addition with the same value is a rename (-HP=2 +HealthPoints=2); documents store values, so nothing else changes. The same name with a new value is a renumber (-A=1 +A=3). Stored values are never migrated: after a renumber or removal they no longer match an option, so both need --allowDataLoss while the schema has documents.

Data Loss Guard

CHANGETYPE with documents (embedded ones included) rejects changes to or from Document, DocumentCollection, Reference, ReferenceCollection, Formula, and from LocalizedText. These are allowed while the schema has no documents.

Lossy changes need --allowDataLoss while documents exist: text to number, logical, date, time or pick list; Number to Integer; number to logical, date or time and back; any type to a pick list; a smaller size or text limit, or a limit added to unlimited text; a new reference target; options dropped by a full option list replacement. The decision uses the change and the document count only. Values that do not convert stay as they are and leave documents invalid until edited. A changed type drops pick.* entries the new type does not use and formula entries (param.*, resultType, knownType). For a shared property, documents of every schema using it count.

To check that a schema is empty, run DATA LIST with --path '*' --take 0.

Read Format

One line per schema and property, labels equal to the write parameter names, defaults omitted. Property attributes print in the order Property, Type, Requirement, Uniqueness, Auto-Generated, Default, Shared, then with --details DisplayName and Description.

Free text is JSON-quoted and single-line. Without --details a Default longer than 80 characters is cut and ends in …; such a value is truncated and must not be passed back.

Examples

The examples run against a copy of the RPG sample project.

GET - schema with its properties:

dnx dotnet-charon -- DATA SCHEMA GET --dataBase rpg.json --schema Quest

#> Schema: Quest, IdGenerator: ObjectId, Group: Story
#>   - Property: Id, Type: Text 24, Requirement: NotNull, Uniqueness: Unique, Auto-Generated
#>   - Property: Title, Type: LocalizedText 200, Requirement: NotEmpty
#>   - Property: Difficulty, Type: PickList Easy=0 Normal=1 Hard=2, Default: "Normal"
#>   - Property: Giver, Type: Reference Hero

CREATE:

dnx dotnet-charon -- DATA SCHEMA CREATE --dataBase rpg.json --name Quest --idGenerator ObjectId --group Story

#> Target: Quest
#> Change: created schema Quest

RENAME (dry run):

dnx dotnet-charon -- DATA SCHEMA RENAME --dataBase rpg.json --schema Disease --newName Illness --dryRun

#> Dry run: nothing was written.
#> Target: Disease
#> Change: renamed schema Disease to Illness
#> Documents: 6 (incl. embedded)

UPDATE:

dnx dotnet-charon -- DATA SCHEMA UPDATE --dataBase rpg.json --schema Quest --displayName "Quests" --icon scroll

#> Target: Quest
#> Change: updated schema Quest: DisplayName, Icon scroll

DELETE - an empty schema needs no extra options:

dnx dotnet-charon -- DATA SCHEMA DELETE --dataBase rpg.json --schema Quest

#> Target: Quest
#> Change: deleted schema Quest
#> Documents: 0 (incl. embedded)

A schema with documents needs --allowDataLoss; its documents are deleted with it:

dnx dotnet-charon -- DATA SCHEMA DELETE --dataBase rpg.json --schema Quirk

#> Schema `Quirk` has 8 documents (incl. embedded). Pass allowDataLoss to delete them with the schema.

dnx dotnet-charon -- DATA SCHEMA DELETE --dataBase rpg.json --schema Quirk --allowDataLoss

#> Target: Quirk
#> Change: deleted schema Quirk
#> Documents: 8 (incl. embedded)

A schema other schemas reference is refused until --cascade Cascade allows removing those properties:

dnx dotnet-charon -- DATA SCHEMA DELETE --dataBase rpg.json --schema Item --allowDataLoss

#> Schema `Item` is referenced by property CurioCleansingOption.Item, property ItemWithCount.Item,
#> property Provision.Item, property Trinket.Item. Set cascade to Cascade to remove these properties too.

dnx dotnet-charon -- DATA SCHEMA DELETE --dataBase rpg.json --schema Item --allowDataLoss --cascade Cascade

#> Target: Item
#> Change: deleted schema Item
#> Change: removed property CurioCleansingOption.Item
#> Change: removed property ItemWithCount.Item
#> Change: removed property Provision.Item
#> Change: removed property Trinket.Item
#> Documents: 39 (incl. embedded)

PROPERTY GET:

dnx dotnet-charon -- DATA SCHEMA PROPERTY GET --dataBase rpg.json --schema Monster --property Name Type

#> Property: Name, Type: LocalizedText 120, Requirement: NotNull
#> Property: Type, Type: PickList Human=1 Beast=2 Unholy=3 Eldritch=4 Corpse=5 Carpentry=6 Crockery=7 Ironwork=8 Thatchery=9 Cosmic=10, Requirement: NotNull, Default: "1"

PROPERTY ADD:

dnx dotnet-charon -- DATA SCHEMA PROPERTY ADD --dataBase rpg.json --schema Quest \
  --name Difficulty --type "PickList Easy Normal Hard" --default Normal

#> Target: Quest.Difficulty
#> Change: added property Quest.Difficulty (PickList Easy=0 Normal=1 Hard=2)

PROPERTY RENAME:

dnx dotnet-charon -- DATA SCHEMA PROPERTY RENAME --dataBase rpg.json --schema Quest --property Giver --newName QuestGiver

#> Target: Quest.Giver
#> Change: renamed property Quest.Giver to QuestGiver
#> Documents: 0 (incl. embedded)

The rename keeps the property Id, so stored values move with it. It warns when the old name still appears in the schema’s display text template or a formula specification; those are not rewritten.

PROPERTY UPDATE:

dnx dotnet-charon -- DATA SCHEMA PROPERTY UPDATE --dataBase rpg.json --schema Quest --property Difficulty \
  --requirement NotNull --after Id

#> Target: Quest.Difficulty
#> Change: updated property Quest.Difficulty: Requirement NotNull, moved after Id

PROPERTY UPDATESPECIFICATION - the only raw key=value surface; --preservePickList and --preserveFormula keep the entries the type system owns:

dnx dotnet-charon -- DATA SCHEMA PROPERTY UPDATESPECIFICATION --dataBase rpg.json --schema Quest \
  --property Difficulty --specification "editor=radio" --preservePickList

#> Target: Quest.Difficulty
#> Change: set specification of Quest.Difficulty

PROPERTY UPDATEPICKLIST:

dnx dotnet-charon -- DATA SCHEMA PROPERTY UPDATEPICKLIST --dataBase rpg.json --schema Quest \
  --property Difficulty --changes "-Hard=2 +Heroic=2 +Legendary"

#> Target: Quest.Difficulty
#> Change: renamed option Hard to Heroic (value 2)
#> Change: added option Legendary (value 3)
#> Documents: 0 (incl. embedded)

PROPERTY CHANGETYPE - a lossy change with documents needs --allowDataLoss:

dnx dotnet-charon -- DATA SCHEMA PROPERTY CHANGETYPE --dataBase rpg.json --schema Hero \
  --property ProvisionsCount --type "Integer 2" --dryRun

#> `Hero.ProvisionsCount` has 3 documents (incl. embedded) and the change may lose data: `Integer 4` → `Integer 2`
#> shrinks the size from 4 to 2 bytes. Pass allowDataLoss to proceed; values that do not convert stay as they are
#> and leave documents invalid until edited.

dnx dotnet-charon -- DATA SCHEMA PROPERTY CHANGETYPE --dataBase rpg.json --schema Hero \
  --property ProvisionsCount --type "Integer 2" --allowDataLoss --dryRun

#> Dry run: nothing was written.
#> Target: Hero.ProvisionsCount
#> Change: changed type of Hero.ProvisionsCount from `Integer 4` to `Integer 2`
#> Documents: 3 (incl. embedded)
#> Warning: Hero.ProvisionsCount: `Integer 4` → `Integer 2` shrinks the size from 4 to 2 bytes

PROPERTY REMOVE:

dnx dotnet-charon -- DATA SCHEMA PROPERTY REMOVE --dataBase rpg.json --schema Quest --property QuestGiver

#> Target: Quest.QuestGiver
#> Change: removed property Quest.QuestGiver
#> Documents: 0 (incl. embedded)

See also