Skip to main content

Interpolation

Agloom supports variable interpolation in canonical files during transpilation. Variables are substituted with adapter-specific paths, environment values, or plugin/project values.

Syntax​

${type:key}
  • type — the variable namespace (agloom, env, or values).
  • key — the variable name. One or more characters not containing }.

Escaping​

Prefix with a backslash to produce the literal text:

\${agloom:VAR}  -->  ${agloom:VAR}
\${env:VAR} --> ${env:VAR}
\${values:VAR} --> ${values:VAR}

The backslash is consumed during interpolation.

Unrecognized Namespaces​

Patterns with namespaces other than agloom, env, or values (e.g., ${foo:bar}) are preserved as literal text without processing.

Variable Namespaces​

agloom​

Adapter-dependent variables built by buildVariables(). Divided into three groups:

Canonical (fixed) Variables​

Values are fixed regardless of the current adapter.

VariableValue
PROJECT_DIRAbsolute path to the project root
AGLOOM_DIR.agloom
AGLOOM_SKILLS_DIR.agloom/skills
AGLOOM_AGENTS_DIR.agloom/agents
AGLOOM_DOCS_DIR.agloom/docs
AGLOOM_SCHEMAS_DIR.agloom/schemas

PROJECT_DIR is the only canonical variable containing an absolute path. All others are relative. Compose them for absolute paths: ${agloom:PROJECT_DIR}/${agloom:AGLOOM_DIR}.

Dynamic (per-current-adapter) Variables​

Values depend on the adapter currently being transpiled. Sourced from the adapter's paths field.

VariableSource
SKILLS_DIRcurrentAdapter.paths.skills
AGENTS_DIRcurrentAdapter.paths.agents
DOCS_DIRcurrentAdapter.paths.docs
SCHEMAS_DIRcurrentAdapter.paths.schemas

A dynamic variable is only present if the corresponding paths field is defined for the current adapter. For example, the agentsmd adapter has empty paths, so none of these variables exist when transpiling for agentsmd.

Static (per-all-adapters) Variables​

Generated for every adapter in the registry that has at least one defined paths field. The prefix is the adapter ID in uppercase.

PatternSource
{PREFIX}_SKILLS_DIRadapter.paths.skills
{PREFIX}_AGENTS_DIRadapter.paths.agents
{PREFIX}_DOCS_DIRadapter.paths.docs
{PREFIX}_SCHEMAS_DIRadapter.paths.schemas

Where {PREFIX} = adapter.id.toUpperCase().

Example values:

VariableValue
CLAUDE_SKILLS_DIR.claude/skills
CLAUDE_AGENTS_DIR.claude/agents
CLAUDE_DOCS_DIR.claude/docs
CLAUDE_SCHEMAS_DIR.claude/schemas
OPENCODE_SKILLS_DIR.opencode/skills
OPENCODE_AGENTS_DIR.opencode/agents
OPENCODE_DOCS_DIR.opencode/docs
OPENCODE_SCHEMAS_DIR.opencode/schemas

Adapters with empty paths (e.g., agentsmd) do not generate static variables.

env​

Environment variables from process.env.

${env:HOME}
${env:PROJECT_NAME}

The .env file in the project root is automatically loaded before transpilation using dotenv. Variables already set in process.env take priority over .env values.

Error on Missing Variable​

If the referenced environment variable is not defined, interpolation fails with:

InterpolationError("Undefined environment variable: <NAME>")

values​

Plugin or project values resolved from variables declarations. See config.md for project variables and plugin-manifest.md for plugin variables.

${values:team_name}
${values:api_token}

Resolution Order​

For plugin values (priority high to low):

  1. values from plugin entry in config.yml (user-provided).
  2. default from variables in plugin.yml.

For project variables:

  1. default from variables in config.yml.

Values containing ${env:VAR} are resolved using process.env during the resolution step.

Isolation​

Each plugin receives only its own resolved values. Plugin A cannot access values from Plugin B. The local project receives its own resolved local values.

Error on Missing Variable​

InterpolationError("Unknown values variable: <NAME>")

Sensitive Variables​

Variables declared with sensitive: true must not be set inline in values. The value must contain at least one ${env:VAR} reference.

  • api_token: "my-secret" — rejected (inline value for sensitive variable).
  • api_token: "${env:API_TOKEN}" — accepted.
  • api_token: "prefix-${env:API_TOKEN}" — accepted (contains ${env:).

Supported File Extensions​

Interpolation is performed on files with the following extensions (case-insensitive comparison):

.md  .txt  .json  .jsonc  .jsonl  .xml  .html  .svg  .toml  .yml  .yaml

Files with other extensions are copied byte-for-byte without interpolation.

Where Interpolation Applies​

  • Instructions transpiler: transformContent applies interpolation to the full transformed content.
  • Agents transpiler: transformContent applies interpolation to the full transformed content.
  • Skills transpiler: writeResults applies interpolation to .md files only.
  • Docs transpiler: writeResults applies interpolation to supported extensions.
  • Schemas transpiler: writeResults applies interpolation to supported extensions.
  • Overlay step: applies interpolation to files with supported extensions before merge/override/patch.

Error Handling​

ConditionError
Unknown ${agloom:NAME}InterpolationError("Unknown agloom variable: <NAME>")
Undefined ${env:NAME}InterpolationError("Undefined environment variable: <NAME>")
Unknown ${values:NAME}InterpolationError("Unknown values variable: <NAME>")

In the instructions and agents transpilers, interpolation errors are wrapped as TransformError or AgentTransformError. In the skills transpiler, they are wrapped as SkillWriteError.

Example​

Canonical content:

Skills are at `${agloom:SKILLS_DIR}`.
Claude skills: `${agloom:CLAUDE_SKILLS_DIR}`.
Project: ${env:PROJECT_NAME}
Team: ${values:team_name}
Escaped: \${env:HOME}

After interpolation for the claude adapter (with PROJECT_NAME=myapp, team_name=platform):

Skills are at `.claude/skills`.
Claude skills: `.claude/skills`.
Project: myapp
Team: platform
Escaped: ${env:HOME}

After interpolation for the opencode adapter:

Skills are at `.opencode/skills`.
Claude skills: `.claude/skills`.
Project: myapp
Team: platform
Escaped: ${env:HOME}