Skip to content

Resource Naming

llms.txt lists every page for an agent
Optional: hand this page to your coding agentThe steps work by hand too.
Show the whole prompt
Read https://intentius.io/chant/guide/resource-naming/.
Rename this project's exports to clear camelCase names, as the page describes, and update every import of each one.
Where environments must coexist, add an `env` build parameter and put it in each resource's name, and check that `npx chant build --env <name>` gives each environment distinct names.
Run `npx chant build` and `npx chant lint`, list every logical name that changed, 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`.

chant discovers resources by scanning exports from your src/ files. The export name becomes the logical resource name that lint output, build logs and cross-file imports show.

Exports must use camelCase; lint rule COR005 enforces it.

// ✅ correct
export const appBucket = new Bucket({ ... });
export const taskQueue = new Queue({ ... });
// ❌ rejected by COR005
export const AppBucket = new Bucket({ ... });
export const app_bucket = new Bucket({ ... });

Name exports after what the resource does, not what it is. Suffix with the resource’s role to distinguish resources of the same type.

// ✅ clear purpose
export const uploadBucket = new Bucket({ ... });
export const taskQueue = new Queue({ ... });
export const apiRole = new Role({ ... });
// ❌ ambiguous
export const bucket1 = new Bucket({ ... });
export const myQueue = new Queue({ ... });

When multiple resources share naming prefixes or tags, extract them into a const object. Template literals keep physical names consistent across the stack.

src/naming-shared-config.ts
import { Bucket, Queue } from "@intentius/chant-lexicon-aws";
const app = { name: "myapp", team: "platform" } as const;
export const sharedDataBucket = new Bucket({
BucketName: `${app.name}-data`,
Tags: [{ Key: "Team", Value: app.team }],
PublicAccessBlockConfiguration: {
BlockPublicAcls: true,
BlockPublicPolicy: true,
IgnorePublicAcls: true,
RestrictPublicBuckets: true,
},
});
export const taskQueue = new Queue({
QueueName: `${app.name}-tasks`,
Tags: [{ Key: "Team", Value: app.team }],
});

Because the config object is as const, chant’s evaluator can resolve every value at build time.

Plain TypeScript replaces count and for_each. Use Array.map to create a set of resources, then destructure the result into named exports:

src/naming-sequential.ts
import { Bucket } from "@intentius/chant-lexicon-aws";
const envs = ["dev", "staging", "prod"] as const;
const buckets = envs.map(
(env) =>
new Bucket({
BucketName: `myapp-${env}-data`,
PublicAccessBlockConfiguration: {
BlockPublicAcls: true,
BlockPublicPolicy: true,
IgnorePublicAcls: true,
RestrictPublicBuckets: true,
},
})
);
export const [devData, stagingData, prodData] = buckets;

Each destructured export (devData, stagingData, prodData) is a distinct named resource that can be referenced from other files via import.

Two builds of the same stack produce identical physical names, so deploying both into one account collides. When a project declares more than one environment, put the environment identity into the names. There are two working shapes.

Declare an env build parameter, bind the ownership marker to it, and interpolate params.env into every name that must be unique per instance:

chant.config.ts
export default {
ownership: { stack: "billing", env: { param: "env" } },
buildParams: {
env: { type: "string", default: "dev" },
},
environments: ["dev", "staging", "prod"],
} satisfies ChantConfig;
src/storage.ts
import { params } from "@intentius/chant/params";
export const uploadBucket = new Bucket({
bucketName: `billing-${params.env}-uploads`,
});

params.env resolves before any file is imported, so the template literal folds to a plain string such as billing-staging-uploads. Build once per environment:

Terminal window
chant build --param env=staging
chant build --param env=prod

The two builds yield disjoint physical names and disjoint ownership markers (chant.intentius.io/env follows the same parameter — see Build-Time Parameters), so --owned filtering, drift, and delete stay scoped to one instance each.

The alternative keeps every environment in one build: instantiate the same composite once per environment, each call passing its own name (web-dev, web-staging, web-prod). This is the layered configuration pattern: a base config, per-environment overrides via object spread, one manifest containing all instances.

Choose per-env builds when environments deploy independently (separate accounts, separate pipelines, short-lived copies); choose the all-in-one shape when one apply should converge every environment at once.

chant build --env <name> sets the CHANT_ENV environment variable before the project is discovered. A build parameter can declare that variable as its fallback, which turns --env into a validated way to supply params.env:

chant.config.ts
buildParams: {
env: { type: "string", default: "dev", env: "CHANT_ENV" },
},
environments: ["dev", "staging", "prod"],

Now chant build --env staging and chant build --param env=staging bind the same value. The --env route has one extra property: the CLI rejects an --env value that is not among the declared environments, so a typo like --env stagign fails before anything builds. --param env= takes precedence over the CHANT_ENV fallback when both are supplied, per the normal precedence rules.

Group related resources in the same file and keep unrelated ones separate. The lint rule COR009 warns when a single file exports eight or more resources, a sign the file may be doing too much.

A typical layout:

src/
storage.ts # buckets, tables
compute.ts # functions, containers
networking.ts # VPCs, subnets, security groups
iam.ts # roles, policies

chant