Managing Lexicons
Show the whole prompt
Read https://intentius.io/chant/guide/managing-lexicons/.
Add the lexicon I name to this project: run `npm install --save-dev @intentius/chant-lexicon-<name>` and add it to `lexicons` in `chant.config.ts`, or declare a lexicon in the project's own source with `name` and `module` as the page shows.
Run `npx chant update`, `npx chant build` and `npx chant lint`, and open a pull request.
Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.Optional: hand this page to your coding agent
Read https://intentius.io/chant/guide/managing-lexicons/.Add the lexicon I name to this project: run `npm install --save-dev @intentius/chant-lexicon-<name>` and add it to `lexicons` in `chant.config.ts`, or declare a lexicon in the project's own source with `name` and `module` as the page shows.Run `npx chant update`, `npx chant build` and `npx chant lint`, and open a pull request.Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.Lexicons are provider-specific type packages that define resource constructors, property types, and intrinsic functions.
Adding a Lexicon
Section titled “Adding a Lexicon”Install the lexicon package and add it to your chant.config.ts:
npm install --save-dev @intentius/chant-lexicon-<name>import type { ChantConfig } from "@intentius/chant";
export default { lexicons: ["<name>"], lint: { extends: ["@intentius/chant/lint/presets/strict"], },} satisfies ChantConfig;Then sync its types into .chant/types/:
npx chant updatechant update (alias chant sync) copies each configured lexicon’s types from node_modules. It does not install a lexicon. Listing one in chant.config.ts without the npm install leaves it out of the sync, with a warning that names the package to install.
A lexicon in your own project
Section titled “A lexicon in your own project”A lexicon you write for one project can live in that project’s source. Name it with the module that exports it instead of a package name:
import type { ChantConfig } from "@intentius/chant";
export default { lexicons: ["fly", { name: "site", module: "./lexicon/index.ts" }],} satisfies ChantConfig;The path is relative to the directory holding chant.config.ts. Every command that loads lexicons reads this one from the module, so the project needs no @intentius/chant-lexicon-site package to install or link.
Some parts of a package-backed lexicon sit at fixed subpaths of the package. When the lexicon is loaded by path there is only the one module, so each part comes from it instead:
| Part | Package-backed lexicon | Lexicon loaded by path |
|---|---|---|
| the plugin | a LexiconPlugin export of the package | a LexiconPlugin export of the module, whose name must equal the declared name |
| Op activities | <package>/op/activities | the plugin’s activities() member, returning { activityName: fn } |
| activity contracts | <package>/op/activity-contracts | the plugin’s activityContracts() member |
| capabilities | a CapabilityPlugin export of the package | a CapabilityPlugin export of the module |
| gate policy evaluator | <package>/gate-policy | an evaluateGatePolicy export of the module |
A lexicon loaded by path has no package version, so the build manifest records none for it. chant update and chant doctor skip it, since there are no package types to copy.
Project files import a lexicon loaded by path by its path, for example import { Page } from "../lexicon". Fold treats an import that resolves to the declared module the same way it treats an import of a lexicon package, with or without --sandbox.
A lexicon split across several files gets a trusted directory, which stands in for the package root. An import of another file under it, such as ../lexicon/resources, is treated like an import of a package subpath: under --sandbox its constructors and composites run in chant’s process, and fold does not fold the file as project source. As with a package subpath, its data exports are not read as values. The directory is the module’s own directory, or the one root names:
lexicons: [{ name: "site", module: "./lexicon/src/index.ts", root: "./lexicon" }],The directory has these bounds:
- inside the project, the directory holding
chant.config.ts - not containing the project’s source directory (
sourceDir, the project root by default) - containing the module
A build whose own source files sit under the directory does not trust it.
A declared root outside these bounds is a config error. When the module’s own directory is outside them, the lexicon gets no directory and only the module file is trusted. That is the case for a module at the project root, so a multi-file lexicon there should move into a directory of its own.
Updating Versions
Section titled “Updating Versions”Update the lexicon package version:
npm update @intentius/chant-lexicon-<name>npx chant updateRun chant update after each version change so .chant/types/ matches the installed package. In CI, run it after npm ci and before any step that reads .chant/types/.
Independent Versioning
Section titled “Independent Versioning”Each lexicon is versioned independently of core and of other lexicons. A spec upgrade PR for k8s bumps only @intentius/chant-lexicon-k8s; merging it triggers publish-on-merge for that package alone.
All lexicons declare @intentius/chant as a peer dependency with a ^ range pinned to the minimum compatible core version (e.g. "^0.13.1"). A lexicon can ship a minor or major version without a core release, and a core minor release leaves lexicon versions where they are.
When installing a lexicon, npm resolves the peer against whichever core version is already in the tree, as long as it satisfies the ^ lower bound.
Installing beside an older core
Section titled “Installing beside an older core”A tool that depends on @intentius/chant and lists lexicons as optional peers can pin a core older than a lexicon’s peer range allows. Installing the lexicon into that tool’s tree then fails or installs nothing: npm 10 has been seen to stop with Cannot read properties of null (reading 'edgesOut'), and npm 11 to exit 0 without installing the package. Two ways round it:
- Raise the tool’s
@intentius/chantto a version inside the lexicon’s peer range, or install a lexicon release whose peer range includes the tool’s core. - Install the lexicon in an empty directory of its own and copy
node_modules/@intentius/chant-lexicon-<name>into the tool’snode_modules.
Check the lexicon’s peer range with npm view @intentius/chant-lexicon-<name> peerDependencies.
How Lexicons Work
Section titled “How Lexicons Work”See Lexicons Overview for the full architecture, including how lexicons provide type definitions, property mappings, and lint rules.