chant workspace init
Synopsis
Section titled “Synopsis”chant workspace init [dir] [--name <name>] [--yes] [--verbose]chant workspace init --profile ideation|app|infra [dir] [--name <name>] [--param name=<display name>] [--from <repo>@<ref>|<chant checkout>] [--yes]Description
Section titled “Description”chant workspace init looks at a repository and proposes a workspace declaration for it. It prints the proposal and the directories that would leave the root project, then asks before it writes chant.workspace.json. Without a terminal to ask on, it writes nothing unless --yes is given. Only the file creates a workspace, so nothing changes until you write it (#2525 rule 1).
The root is dir when it’s given, otherwise the top of the git repository holding the current directory. The command refuses to run where a chant.workspace.json or .jsonc already exists.
It runs no project code. It reads file names, package.json files, and the text of each member’s chant.config.ts or chant.config.json for its ownership.stack. In a git repository the file names come from git, which leaves out ignored files and node_modules.
What it proposes
Section titled “What it proposes”| Found | Proposed entry |
|---|---|
a chant.config.ts or chant.config.json at the root | a chant member with directory ".", named root |
| any other outermost chant project | a chant member |
a directory with its own chant.workspace.json | a workspace member; nothing inside it is looked at |
an npm workspace package, or any other package.json outside those, with no chant project | an other member, with a because |
chant projects under an examples, example, samples, test, tests or fixtures directory | an example group |
Projects inside a test runner’s directory, such as __fixtures__, stay with the package around them.
An example tree whose subdirectories are mostly projects gets one glob, such as examples/*. Trees that differ in one path segment merge, as lexicons/aws/examples/* and lexicons/gcp/examples/* become lexicons/*/examples/*, when the merged glob claims no member. A tree that is mostly something else lists its projects one by one. Groups are named after the tree: examples, fixtures, or with a prefix such as lexicon-examples.
Member names come from package.json without the npm scope and without a leading <workspace>-, so @intentius/chant-lexicon-aws in the chant workspace becomes lexicon-aws. Without a usable package name, the directory’s name is used. The workspace’s name is --name, else the repository name from the origin remote, else the root package’s name, else the directory’s name.
The proposal is a starting point to review. It is read back through the same validation as any declaration before it is shown.
What leaves the root project
Section titled “What leaves the root project”Before it asks, init prints every member directory and example-group match that would leave the root project, with the number of .ts source files each holds (tests left out). A group’s matches are summed on one line, and a match inside a member’s directory leaves with that member. --verbose prints each directory and file.
DIRECTORY OWNER .TS FILES docs docs 2 33 directories examples 294 lexicons/aws lexicon-aws 337 packages/core core 562 2 directories fixtures 10Once the file is written, root-level chant build, lint, run and audit stop reading these directories (#2527). chant workspace build and its siblings cover them, each member with its own chant (#2537).
Profiles
Section titled “Profiles”--profile starts a workspace from one of the reference workspace’s three profiles instead of proposing one from what is there (#3174, ws-096). Each declares only what its kind of user needs, so nothing about a factory or an app is asked of a workspace that doesn’t build one.
| Profile | What it declares |
|---|---|
ideation | The decision, work and answer record kinds, and a stub app member of the app kind that answers /health and shows the workspace’s name. No box and no factory |
app | The same records, and an app member whose box block runs it as a service and declares the factory: it builds app, and the app’s tests are the verdict |
infra | The same records, and an estate member, network, a chant project on the terraform lexicon. Its box block declares only the factory, checked by a lint and a build, with no app member and no box services, so the factory runs on a fountain steward |
chant init --from copies the profile from reference-workspace/profiles/<profile> in the chant repository at the tag of the chant you run (chant-v<version>). The copy has a lineage lock, so chant workspace upgrade takes later versions of it. --from reads the profiles from another <repo>@<ref>, or from a chant checkout on disk. --param name=<display name> sets the name the stub app shows, and --name sets the declaration’s name. Each profile passes chant workspace check as it is copied.
Ownership stacks
Section titled “Ownership stacks”Each chant member needs an ownership.stack of its own (#2538, ws-037). Ownership markers carry no member name, so the stack is what tells two members’ resources and receipts apart, and the WSP071 check fails when two members share one (see Ledgers). Init prints one distinct stack per member after the directories that leave the root project:
MEMBER STACK CHANGE api shop keep web web rename from "shop" in services/web/chant.config.json, which another member uses jobs jobs set ownership.stack in services/jobs/chant.config.tsMembers are taken in declaration order, so the root member and then the outermost directories keep their stacks first. A stack that only one member uses is kept. A shared stack stays with the first member that uses it, and each other member gets its member name. A member that sets no stack gets its member name too, with a number added when another member already uses that name. A stack the config computes rather than writes as a plain string is listed as computed, with the member name as the proposal.
The stack stays in the member’s config and the declaration gains no marker key, so init never writes these changes. Apply them by hand. Renaming the stack of a member that is already deployed changes the markers on its resources, so resources deployed under the old stack are no longer matched as that member’s.
Options
Section titled “Options”| Option | Effect |
|---|---|
dir | The directory to propose a workspace for. Defaults to the git root. |
--name <name> | The workspace’s name, in the name grammar. |
--yes | Write the file without asking. |
--verbose | List every directory and file leaving the root project. |
--profile <profile> | Copy the ideation, app or infra profile instead of proposing a declaration. See Profiles. |
--from <source> | With --profile, where the profiles are read: a <repo>@<ref>, or a chant checkout on disk. Defaults to the chant repository at this chant’s release tag. |
--param name=<value> | With --profile, the display name the profile’s stub app shows. |
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
| 0 | The proposal was shown, and written if confirmed. Declining writes nothing and still exits 0. |
| 1 | A declaration already exists, --name is invalid, dir doesn’t exist, or the profile is unknown or couldn’t be copied. |
Examples
Section titled “Examples”# See what a declaration for this repository would look likechant workspace init
# Write it without a prompt, for a scriptchant workspace init --yes --name acme
# Start an infra workspace whose factory builds its estatechant workspace init estate --profile infra --name estate --yes