Skills
Lexicon authors can include skill files: markdown documents that teach AI agents how to work with the lexicon’s resource types and patterns. They live in lexicons/<name>/src/skills/*.md and are returned from the plugin’s skills() member as SkillDefinition[].
SkillDefinition (packages/core/src/lexicon.ts:191) has three required fields
and five optional ones.
| Field | Required | Meaning |
|---|---|---|
name | yes | The skill’s identifier. Becomes the skills/<name>/SKILL.md directory on install |
description | yes | One-line summary |
content | yes | The full markdown, frontmatter included, read from the .md file |
triggers | no | SkillTrigger[] |
parameters | no | SkillParameter[] |
examples | no | SkillExample[] |
preConditions | no | string[] |
postConditions | no | string[] |
No shipped lexicon populates the five optional fields; name, description and content are the working surface.
Op-Aware Skills
Section titled “Op-Aware Skills”If your lexicon contributes Op step builders — functions users import into *.op.ts files — add a dedicated section to your skill content that shows how to use them. Agents authoring Op files will find these instructions alongside your resource authoring patterns.
## Using [My Lexicon] resources in Ops
When your Op needs to apply resources from this lexicon, use the step buildersexported from `@intentius/chant-lexicon-my-lexicon`:
\`\`\`typescriptimport { Op, phase } from "@intentius/chant/op";import { myLexiconApply } from "@intentius/chant-lexicon-my-lexicon";
export default Op({ name: "my-deploy", phases: [ phase("Deploy", [myLexiconApply("dist/output.yaml", { profile: "longInfra" })]), ],});\`\`\`
The MCP server exposes `op-run`, `op-status`, and `op-signal` so you can startand monitor this Op programmatically.The fountain lexicon’s chant-fountain-ops.md is the reference example — it teaches agents how to declare a steward, run an op on it, and resolve a gate with chant approve.
Not all lexicons need Op-aware skills. Synthesis-only lexicons (those that don’t export step builders) don’t need this section.
The 3-Skill Pattern
Section titled “The 3-Skill Pattern”A mature lexicon should include 3 skills covering different scopes:
All three files live under lexicons/azure/src/skills/.
| Skill | Purpose | Example |
|---|---|---|
| Core | Syntax, resource types, basic usage | chant-azure.md, ARM resource declarations, intrinsics, pseudo-parameters |
| Platform-specific | Cloud and platform security and integration patterns | chant-azure-security.md, managed identity, encryption, TLS, NSG |
| Advanced patterns | Complex usage, composites, multi-resource patterns | chant-azure-patterns.md, linked templates, conditional resources, tagging strategies |
Skill File Format
Section titled “Skill File Format”Each skill file is a markdown document with YAML frontmatter:
---skill: chant-my-lexicondescription: Core deployment workflow for My Lexicon resourcesuser-invocable: true---# Resource Authoring
When writing resources with chant and this lexicon:
1. Import types directly from the lexicon package2. Use intrinsic functions for dynamic values3. Reference other resources via direct importsFrontmatter Fields
Section titled “Frontmatter Fields”chant does not parse this frontmatter. The file’s whole text, frontmatter
included, becomes SkillDefinition.content and is written verbatim to
skills/<name>/SKILL.md, where the agent harness reads it. The name and
description that chant itself uses come from the plugin’s skill spec, not from
here. Keep the two in sync by convention.
| Field | Description |
|---|---|
skill | The skill name. Match the name registered in plugin.ts |
description | One-line summary of what the skill covers |
user-invocable | true if the skill can be invoked directly by the user |
Skill Content Guidelines
Section titled “Skill Content Guidelines”Good skill content:
- Starts with an overview of what the skill covers and when to use it
- Uses real, runnable TypeScript snippets
- References the post-synth checks a security skill relates to, by id
- Shows how to use composites for common patterns
- Includes quick-reference tables for functions and parameters
Registering Skills in Plugin
Section titled “Registering Skills in Plugin”Return skill definitions from your plugin’s skills() method:
Use createSkillsLoader from packages/core/src/lexicon-plugin-helpers.ts. It
resolves skills/ relative to the module you pass import.meta.url from, reads
each file, and returns a zero-argument function of the shape skills() wants. A
missing file yields an empty content rather than throwing:
import { createSkillsLoader } from "@intentius/chant/lexicon-plugin-helpers";
export const myPlugin: LexiconPlugin = { // ... skills: createSkillsLoader(import.meta.url, [ { file: "chant-my-lexicon.md", name: "chant-my-lexicon", description: "Build, validate, and deploy My Lexicon output from a chant project", }, { file: "chant-my-lexicon-security.md", name: "chant-my-lexicon-security", description: "Security patterns and the checks that enforce them", }, ]),};The file field is the filename inside src/skills/; every other field of
SkillFileSpec is a SkillDefinition field minus content. Fifteen of the
seventeen lexicons wire skills this way. lexicons/fly/src/plugin.ts:79 is a
short worked example; k3s keeps a hand-rolled loop for the same effect.
Installation
Section titled “Installation”Skills are installed automatically when you initialize a project:
chant init --lexicon my-lexicon my-infrachant init --lexicon my-lexicon --skill chant-my-lexicon my-infra # just oneEach skill is written to skills/<name>/SKILL.md under the project root
(packages/core/src/cli/commands/init.ts:462). --skill filters to a single
skill by name and warns if no skill matches. Skill installation is best-effort.
When the lexicon package cannot be loaded, chant init still succeeds and
installs nothing.
Lifecycle
Section titled “Lifecycle”| Command | Effect |
|---|---|
chant init | Writes each skill to skills/<name>/SKILL.md |
chant init --skill <name> | Writes only that skill |
chant update | Rewrites skills/<name>/SKILL.md for every loaded plugin |
Collecting Skills for Packaging
Section titled “Collecting Skills for Packaging”When building a lexicon bundle, use collectSkills from core to gather skill definitions:
import { collectSkills } from "@intentius/chant/codegen/package";
const skills = collectSkills(myPlugin.skills!());collectSkills returns a Map keyed by <name>.md. Pass it as the
collectSkills member of the packagePipeline config, which is typed
() => Map<string, string>.
Reference
Section titled “Reference”Sixteen of the seventeen lexicons ship skills. Only k3d ships none
(lexicons/k3d/src/plugin.ts returns []).
| Lexicon | Skills | Count |
|---|---|---|
| AWS | chant-aws, chant-aws-eks, chant-aws-carve-terraform | 3 |
| Azure | chant-azure, chant-azure-security, chant-azure-patterns, chant-azure-aks | 4 |
| Cedar | chant-cedar-authoring, chant-cedar-avp-embedding, chant-cedar-dogwood, chant-cedar-meta-policy | 4 |
| Control Plane | chant-cpln, chant-cpln-workloads, chant-cpln-secrets | 3 |
| Docker | chant-docker, chant-docker-patterns | 2 |
| Fly | chant-fly, chant-fly-ops, chant-fly-patterns, chant-fly-sprites | 4 |
| Forgejo | chant-forgejo | 1 |
| Fountain | chant-fountain, chant-fountain-ops, chant-fountain-secrets, chant-fountain-locked-sandboxes | 4 |
| GCP | chant-gcp, chant-gcp-security, chant-gcp-patterns, chant-gcp-gke | 4 |
| GitHub | chant-github, chant-github-patterns, chant-github-security | 3 |
| GitLab | chant-gitlab, chant-gitlab-patterns, chant-gitlab-migrate | 3 |
| Helm | chant-helm, chant-helm-patterns, chant-helm-security | 3 |
| K3s | chant-k3s | 1 |
| K8s | chant-k8s, chant-k8s-patterns, chant-k8s-deployment-strategies, chant-k8s-security, chant-k8s-eks, chant-k8s-gke, chant-k8s-aks, chant-k8s-argo, chant-k8s-flux, chant-k8s-ray | 10 |
| Render | chant-render, chant-render-patterns | 2 |
Next Steps
Section titled “Next Steps”With skills defined, the final step is to package and publish your lexicon.