Skip to content

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.

FieldRequiredMeaning
nameyesThe skill’s identifier. Becomes the skills/<name>/SKILL.md directory on install
descriptionyesOne-line summary
contentyesThe full markdown, frontmatter included, read from the .md file
triggersnoSkillTrigger[]
parametersnoSkillParameter[]
examplesnoSkillExample[]
preConditionsnostring[]
postConditionsnostring[]

No shipped lexicon populates the five optional fields; name, description and content are the working surface.

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 builders
exported from `@intentius/chant-lexicon-my-lexicon`:
\`\`\`typescript
import { 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 start
and 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.

A mature lexicon should include 3 skills covering different scopes:

All three files live under lexicons/azure/src/skills/.

SkillPurposeExample
CoreSyntax, resource types, basic usagechant-azure.md, ARM resource declarations, intrinsics, pseudo-parameters
Platform-specificCloud and platform security and integration patternschant-azure-security.md, managed identity, encryption, TLS, NSG
Advanced patternsComplex usage, composites, multi-resource patternschant-azure-patterns.md, linked templates, conditional resources, tagging strategies

Each skill file is a markdown document with YAML frontmatter:

---
skill: chant-my-lexicon
description: Core deployment workflow for My Lexicon resources
user-invocable: true
---
# Resource Authoring
When writing resources with chant and this lexicon:
1. Import types directly from the lexicon package
2. Use intrinsic functions for dynamic values
3. Reference other resources via direct imports

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.

FieldDescription
skillThe skill name. Match the name registered in plugin.ts
descriptionOne-line summary of what the skill covers
user-invocabletrue if the skill can be invoked directly by the user

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

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:

src/plugin.ts
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.

Skills are installed automatically when you initialize a project:

Terminal window
chant init --lexicon my-lexicon my-infra
chant init --lexicon my-lexicon --skill chant-my-lexicon my-infra # just one

Each 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.

CommandEffect
chant initWrites each skill to skills/<name>/SKILL.md
chant init --skill <name>Writes only that skill
chant updateRewrites skills/<name>/SKILL.md for every loaded plugin

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>.

Sixteen of the seventeen lexicons ship skills. Only k3d ships none (lexicons/k3d/src/plugin.ts returns []).

LexiconSkillsCount
AWSchant-aws, chant-aws-eks, chant-aws-carve-terraform3
Azurechant-azure, chant-azure-security, chant-azure-patterns, chant-azure-aks4
Cedarchant-cedar-authoring, chant-cedar-avp-embedding, chant-cedar-dogwood, chant-cedar-meta-policy4
Control Planechant-cpln, chant-cpln-workloads, chant-cpln-secrets3
Dockerchant-docker, chant-docker-patterns2
Flychant-fly, chant-fly-ops, chant-fly-patterns, chant-fly-sprites4
Forgejochant-forgejo1
Fountainchant-fountain, chant-fountain-ops, chant-fountain-secrets, chant-fountain-locked-sandboxes4
GCPchant-gcp, chant-gcp-security, chant-gcp-patterns, chant-gcp-gke4
GitHubchant-github, chant-github-patterns, chant-github-security3
GitLabchant-gitlab, chant-gitlab-patterns, chant-gitlab-migrate3
Helmchant-helm, chant-helm-patterns, chant-helm-security3
K3schant-k3s1
K8schant-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-ray10
Renderchant-render, chant-render-patterns2

With skills defined, the final step is to package and publish your lexicon.