Schema and bundles
Inspect the deployed schema, sync, add and manage its bundles, and compare what your code declared with what the workspace runs.
Objects are declared in code, in bundles. From a terminal you can list objects, inspect one, sync the bundles your project declares, add the pre-built bundles a workspace may add, list and remove the bundles a workspace holds, and diff the deployed schema against the shared runtime. schema, pull and diff only read.
Inspect the deployed schema
standards schema liststandards schema inspect contactsinspect accepts an object name or id and returns its attributes, types and views.
standards schema groupsgroups lists the bundles that own objects, each with its label.
Sync, list and remove bundles
A bundle is a set of objects, views, pages and agents declared with bundle(name, label). See Bundles.
standards bundles syncsync discovers the bundles of the project (standards/bundles/*.ts by default, or the patterns of standards.config.ts), then syncs each one, the bundles it .uses() first. It prints <name> applied <hash> or <name> unchanged <hash>, and exits 1 at the first refusal. --cwd <dir> sets the project root.
standards bundles listlist shows each installed bundle's name, mode (synced or added), origin, hash and install time.
Removing a synced bundle demotes its objects to custom objects. Records are kept.
standards bundles remove <name> --yesThe command refuses to run without --yes, and refuses core, a bundle a host declares in code, an added copy and a bundle another one uses.
Add a bundle
An added bundle is a copy the workspace owns: its objects, views and agents are created once, and you edit them like anything you built yourself. Listing and previewing need architect: read on your key; adding needs architect: create.
| Command | What it does | What it prints |
|---|---|---|
standards bundles available | Lists the bundles the workspace may add, each with the bundles it uses and whether it is installed. | The bundles. |
standards bundles preview <names...> | Plans an add against the workspace. Writes nothing. | { pieces, fingerprint }. |
standards bundles add <names...> --fingerprint <fingerprint> | Adds the previewed plan. | { added, failed }. |
| Flag | Commands | Description |
|---|---|---|
--locale <locale> | all three | en (default) or fr. On preview and add it is the language the pieces are compiled in. |
--with-samples | preview, add | Also adds the bundles' sample records. |
--fingerprint <fingerprint> | add | Required. The fingerprint preview returned. |
--decision <pieceId>=<choice> | add | How to settle one collision: bind, skip or rename:<name>. Repeat it once per collision. |
Adding a bundle also adds the bundles it uses. An unknown --locale, or a --decision that does not read <pieceId>=bind, <pieceId>=skip or <pieceId>=rename:<name>, is refused before a request is sent.
An add is two calls with the same bundles. preview returns one piece per object, view or agent, then a fingerprint of that plan:
standards bundles preview <name> --locale enEach piece has a pieceId and a status. new is added as is. collides means the workspace already has something under that name (existingName), and the add needs a decision for it, with two exceptions: a page or tab whose name is taken is added under a suffixed name, and a piece marked installed: true (an earlier add of the bundle put it there) is skipped, or bound when a kept piece needs it:
| Decision | Effect |
|---|---|
bind | Uses the existing object instead of adding one. Only an object can be bound. |
skip | Leaves the piece out. A piece another kept piece needs cannot be skipped. |
rename:<name> | Adds the piece under <name>. A page's <name> is its API name: lowercase letters, digits, - and _, at most 40 characters, not taken. |
A piece with installable: false carries a reason, and the add is refused unless you skip it. Pass the same bundles, the fingerprint and one --decision per collision to add:
standards bundles add <name> --locale en \
--fingerprint <fingerprint> \
--decision <objectPieceId>=bind \
--decision <viewPieceId>=rename:<newName>The add is refused with nothing written when a colliding piece that needs a decision has none, or when the workspace changed since the preview, so the fingerprint no longer matches: run preview again and use the new fingerprint.
Pull
pull reads the deployed schema and the shared runtime, then prints reconciliation guidance. It writes no file and changes nothing in the workspace.
standards pullstandards pull --json--json prints the canonical shared state instead of the guidance. Both forms only see what has been applied: unbuilt local TypeScript is not part of the comparison.
Diff
diff compares the deployed schema with the shared runtime and lists every change, addressed by object, attribute, relation, view or content name.
standards diffstandards diff --json| Exit code | Meaning |
|---|---|
0 | No differences. |
1 | Differences exist. The list is on stdout. |
2 | Authentication, transport or schema-contract error. The message is on stderr. |
Use it as a CI gate:
standards diff --json
case $? in
0) ;;
1) echo "runtime drifted from source"; exit 1 ;;
*) echo "diff failed"; exit 2 ;;
esacRuntime additions stay listed until your declarations absorb them. A replaced content or a reordered view stays listed as a retained copy even once it matches the source again: deploying new builders does not clear it, resetting it to the source in architect mode does.
Codemod: builder shorthand
Builders take the name and the label as positional arguments: object("services", "Service"), text("url", "URL"). The { name, label } form is removed. codemod builder-shorthand rewrites a codebase to the new form.
npx @standards/cli codemod builder-shorthand srcnpx @standards/cli codemod builder-shorthand src --dry-runIt takes any number of files or directories (default .) and prints Rewrote N calls in M files.; --dry-run reports without writing. It does not format: run your formatter afterwards.
Codemod: palette
Colour ids moved from nineteen Tailwind names (gray, blue, green…) to the Standards palette. A schema still declaring an old name no longer compiles. codemod palette renames each old id to its nearest hue; options sharing a colour in one list keep distinct hues.
npx @standards/cli codemod palette src --dry-runIt rewrites every color: "<old id>" property, every variant="<old id>" JSX attribute and every .color("<old id>") argument under the paths you give, Standards code or not: point it at your schema and UI folders, not at a whole repository with charts or other component libraries. --dry-run lists each file it would rewrite with its count; run it first, then without the flag. It does not format: run your formatter afterwards.
Only functions imported from @standards/schema or @standards/client are rewritten; a same-named function from any other module, including a relative one, is left alone and not reported. --relative-imports also treats relative imports as Standards builders, which only the Standards monorepo itself needs.
A call it cannot rewrite safely is left untouched and listed as file:line:col callee reason, for instance a config that is not an object literal, a spread, an unsupported key, a comment inside the config (the rewrite would drop it), an overlapping rewrite or a namespace import. The command then exits 1. Rewrite those calls by hand as fn(name, label) and run it again.
Codemod: image
An object declares its record images with .image({ shape, from }); .imageShape() is removed. codemod image rewrites a codebase:
npx @standards/cli codemod image src --dry-runIt rewrites every .imageShape(x) call to .image({ shape: x }), whatever the expression x, and every read of .appearance.imageFileId to .appearance.image?.fileId, optional chaining included. A second run changes nothing. It prints Rewrote N references in M files.; --dry-run reports without writing. An assignment to appearance.imageFileId cannot become image?.fileId, so it is left untouched and listed as file:line:col, and the command exits 1. It does not format: run your formatter afterwards. Other uses of the old names are not rewritten, so your compiler reports them: a read of an object definition's imageShape (now image.shape), of a relation option's objectImageShape (now objectImage.shape) and a destructured { imageFileId }.
Next steps
- Schema ownership: what a bundle owns and what happens on removal.
- Bundles: declare and sync the schema in code.
- CLI: exit codes and output formats.
- Book a demo