Skip to main content

Transpilers

Agloom uses a pipeline of transpiler modules to convert canonical files into agent-specific output. Each module handles a specific content type.

Pipeline Overview

Transpiler modules execute in this fixed order for each adapter:

  1. Instructions — transforms AGLOOM.md into agent-specific instruction files.
  2. Commands — transforms slash-command definitions from .agloom/commands/ to agent-specific directories.
  3. Skills — copies skill packages from .agloom/skills/ to agent-specific directories.
  4. Agents — transforms agent definitions from .agloom/agents/ to agent-specific directories.
  5. Docs — copies documentation files from .agloom/docs/ to agent-specific directories.
  6. Schemas — copies schema files from .agloom/schemas/ to agent-specific directories.
  7. Overlay step — applies overlay files, MCP configuration, and permissions.

Steps 1-6 run independently for each adapter. Step 7 (overlay) applies after all transpiler modules and handles cross-cutting concerns like file merging and adapter-specific overrides.

Commands runs before Skills to ensure correct priority for the Codex adapter: commands are converted to skill packages first, and skills from the Skills transpiler overwrite them when names conflict.

Instructions Transpiler

Source: AGLOOM.md in the project root and **/AGLOOM.md in subdirectories

Operation: Transforms content — parses YAML frontmatter, applies per-agent override fields, filters agent-specific sections in the Markdown body.

Agent-Specific Sections

The body may contain agent-specific sections delimited by HTML comments:

<!-- agent:claude -->

This content only appears in CLAUDE.md output.

<!-- /agent:claude -->

<!-- agent:agentsmd -->

This content only appears in AGENTS.md output.

<!-- /agent:agentsmd -->

Content outside sections appears in all outputs. Sections matching the target agent are unwrapped (tags removed, content kept). Non-matching sections are removed entirely.

Valid Agent IDs for Instructions

Only agents with their own instruction file format are valid in <!-- agent:id --> tags:

Agent IDValid?Reason
claudeYesHas CLAUDE.md
agentsmdYesHas AGENTS.md
geminiYesHas GEMINI.md
opencodeNoUses AGENTS.md via agentsmd
kilocodeNoUses AGENTS.md via agentsmd
codexNoUses AGENTS.md via agentsmd

Frontmatter Override

The canonical frontmatter may contain an override block with per-agent key overrides (shallow merge):

---
override:
claude:
someKey: value
---

The override key is removed from the output. Keys from override[agentId] replace top-level keys in the frontmatter.

Output Per Adapter

AdapterInputOutput
claudeAGLOOM.mdCLAUDE.md (same relative location)
agentsmdAGLOOM.mdAGENTS.md (same relative location)
geminiAGLOOM.mdGEMINI.md (same relative location)
opencode(no-op)(no output)
kilocode(no-op)(no output)
codex(no-op)(no output)

Commands Transpiler

Source: .agloom/commands/ directory (recursive, including subdirectories)

Operation: Transforms command definitions — parses YAML frontmatter, applies per-agent override fields, filters agent-specific sections in the Markdown body. Same transformation mechanism as the agents transpiler.

Canonical Format

A command is a single .md file in .agloom/commands/ with YAML frontmatter and a Markdown body. Files may be organized into subdirectories of arbitrary depth (e.g., .agloom/commands/git/commit.md).

The command name is derived from the file path relative to the commands directory, without the .md extension:

  • commands/deploy.md — name: deploy
  • commands/git/commit.md — name: git/commit

Frontmatter Override

Same mechanism as the agents transpiler:

---
description: Deploy to production
override:
gemini:
description: Deploy the app to production
claude:
argument-hint: "[environment]"
---

The override key is removed from the output. Keys from override[agentId] replace top-level keys in the frontmatter.

Subdirectory Handling

Adapters use one of two modes for subdirectory structure:

ModeBehaviorAdapters
PreserveSubdirectory structure is maintained in the outputclaude, gemini
FlattenAll files are placed in the root of the target directoryopencode, kilocode, codex

When flattening, if files from different subdirectories have the same filename, transpilation fails with a name conflict error.

Output Per Adapter

AdapterOutput DirectoryFormatSubdirs
claude.claude/commands/MarkdownPreserve
opencode.opencode/commands/MarkdownFlatten
kilocode.kilo/commands/MarkdownFlatten
gemini.gemini/commands/TOML (.toml extension)Preserve
codex.agents/skills/<name>/SKILL.mdMarkdown (as skill package)Flatten (hyphen-join)
agentsmd(no output)----

Gemini adapter: After standard content transformation, the adapter converts the result from Markdown to TOML. Frontmatter fields become top-level TOML keys. The Markdown body (if non-empty) becomes the prompt key. The output file extension changes from .md to .toml.

Codex adapter: Since Codex does not support project-level commands, each command is converted into a skill package at .agents/skills/<name>/SKILL.md. Subdirectory separators in the command name are replaced with hyphens (e.g., git/commit becomes git-commit). If a skill with the same name exists in .agloom/skills/, the skill takes priority (it overwrites the command-generated file because Skills runs after Commands).


Skills Transpiler

Source: .agloom/skills/<name>/ directories

Operation: Copies skill packages (directory with SKILL.md and supporting files) into agent-specific skill directories. No content transformation — files are copied as-is, except .md files undergo interpolation when variables are provided.

Canonical Format

A skill is a directory in .agloom/skills/<name>/ containing a SKILL.md file (YAML frontmatter + Markdown body) and optional supporting files. The transpiler does not validate or transform skill content.

Output Per Adapter

Skills are copied to the adapter's paths.skills directory:

AdapterOutput Directory
claude.claude/skills/<name>/
opencode.opencode/skills/<name>/
kilocode.kilo/skills/<name>/
codex.agents/skills/<name>/
gemini.gemini/skills/<name>/
agentsmd(no output — empty paths)

Agents Transpiler

Source: .agloom/agents/<name>.md files

Operation: Transforms agent definitions — parses YAML frontmatter, applies per-agent override fields, filters agent-specific sections in the Markdown body. Same transformation mechanism as instructions transpiler (but without allowedAgentIds validation on agent-specific sections).

Frontmatter Override

Same mechanism as instructions transpiler. Example:

---
name: code-reviewer
model: sonnet
override:
opencode:
model: anthropic/claude-sonnet-4-5
claude:
permissionMode: plan
---

Output Per Adapter

Agents are copied to the adapter's paths.agents directory:

AdapterOutput Directory
claude.claude/agents/<name>.md
opencode.opencode/agents/<name>.md
kilocode.kilo/agents/<name>.md
codex.codex/agents/<name>.md
gemini.gemini/agents/<name>.md
agentsmd(no output — empty paths)

Docs Transpiler

Source: .agloom/docs/ directory

Operation: Copies documentation files to agent-specific docs directories. Markdown and other text files undergo interpolation when variables are provided.

Output Per Adapter

AdapterOutput Directory
claude.claude/docs/
opencode.opencode/docs/
kilocode.kilo/docs/
codex.codex/docs/
gemini.gemini/docs/
agentsmd(no output)

Schemas Transpiler

Source: .agloom/schemas/ directory

Operation: Copies schema files (JSON Schema, OpenAPI, etc.) to agent-specific schemas directories. Text files undergo interpolation when variables are provided.

Output Per Adapter

AdapterOutput Directory
claude.claude/schemas/
opencode.opencode/schemas/
kilocode.kilo/schemas/
codex.codex/schemas/
gemini.gemini/schemas/
agentsmd(no output)

MCP Transpiler

Source: .agloom/mcp.yml or .agloom/mcp.json

Operation: Transforms the canonical MCP server configuration into adapter-specific formats. Supports three transport types: stdio (local process), HTTP (streamable HTTP), and SSE (Server-Sent Events).

Canonical Format

mcpServers:
context7:
command: npx
args: ["-y", "@upstash/context7-mcp@latest"]
filesystem:
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem"]
env:
ROOT_DIR: "${env:PROJECT_ROOT}"
includeTools:
- read_file
- list_directory
figma:
type: http
url: https://mcp.figma.com/mcp
headers:
X-Figma-Region: us-east-1
asana:
type: sse
url: https://mcp.asana.com/sse
headers:
Authorization: "Bearer ${env:ASANA_TOKEN}"

Common Fields

FieldTypeDefaultDescription
type"stdio" | "http" | "sse""stdio"Transport type.
includeToolsarray<string>-Whitelist of tools (mutually exclusive with excludeTools).
excludeToolsarray<string>-Blacklist of tools (mutually exclusive with includeTools).

Stdio Fields (when type is "stdio" or omitted)

FieldTypeDescription
commandstringRequired. Command to start the server.
argsarray<string>Command arguments.
envobjectEnvironment variables for the process.

Fields url and headers are forbidden for stdio.

HTTP/SSE Fields (when type is "http" or "sse")

FieldTypeDescription
urlstringRequired. URL of the remote MCP server.
headersobjectHTTP headers sent when connecting.

Fields command, args, and env are forbidden for http/sse.

Discovery-Level Tool Filtering

The includeTools/excludeTools fields control which tools an MCP client advertises to the model. This is not the same as runtime permission gating (which is handled by .agloom/permissions.yml).

Only adapters whose target format has native filtering fields apply these canonically:

AdapterNative supportMechanism
codexYesenabled_tools / disabled_tools in .codex/config.toml
geminiYesincludeTools / excludeTools in .gemini/settings.json
claudeNoIgnored with warning. Use permissions.yml instead.
opencodeNoIgnored with warning. Use permissions.yml instead.
kilocodeNoIgnored with warning. Use permissions.yml instead.

Output Per Adapter

AdapterOutput FileTransport SupportNotes
claude.mcp.jsonstdio, http, sseAll transports passed through with explicit type field.
opencodeopencode.jsonstdio, httpSSE servers skipped with warning. HTTP mapped to type: "remote".
codex.codex/config.tomlstdio, httpSSE servers skipped with warning. Headers in http_headers sub-table.
gemini.gemini/settings.jsonstdio, http, sseHTTP mapped to httpUrl key, SSE to url key. No type field in output.
kilocodekilo.jsoncstdio, http, sseHTTP mapped to type: "streamable-http". Stdio entries have no type field.

Only .agloom/mcp.yml or .agloom/mcp.json may exist — not both simultaneously.


Permissions Transpiler

Source: .agloom/permissions.yml or .agloom/permissions.json

Operation: Transforms the canonical permissions configuration into adapter-specific formats.

Canonical Format

The canonical format uses first-match-wins semantics: the first matching rule in the array determines the action. Each section is an ordered array of { pattern: action } objects.

shell:
- "git status *": allow
- "git push *": ask
- "*": deny
mcp:
- "bitbucket:*": allow
- "*:*": ask
file:
- "src/**": write
- "**": read
SectionPattern FormatActions
shellGlob matched against full command stringallow, ask, deny
mcp<server>:<tool> formatallow, ask, deny
fileGlob matched against file pathdeny, read, write

All sections are optional.

Output Per Adapter

AdapterOutput FileSupported SectionsNotes
claude.claude/settings.jsonshell, mcpFirst-match-wins preserved via preprocessing. file and ask action not supported.
opencodeopencode.jsonshell, mcp, fileRule order inverted (OpenCode uses last-match-wins).
codex.codex/rules/agloom.rulesshellStarlark-like prefix_rule format. mcp and file sections skipped with warning.
gemini.gemini/policies/agloom.tomlshell, mcpTOML [[rule]] format with priority-based ordering. file section skipped with warning.
kilocodekilo.jsoncshell, mcp, fileRule order inverted (last-match-wins). Deep-merged with MCP output in the same file.

Only .agloom/permissions.yml or .agloom/permissions.json may exist — not both simultaneously.


Overlay Step

The overlay step runs after all transpiler modules. It applies per-adapter overlay files from .agloom/overlays/<adapterId>/ to the project root.

File Merge Strategies

The strategy for each file is determined by its extension and naming:

ConditionStrategy
Has .override suffix (e.g., settings.override.json)Override — full replacement.
Has .patch suffix + merge-eligible extensionPatch — declarative operations.
Merge-eligible extension (.json, .jsonc, .yaml, .yml, .toml)Overlay — deep merge.
All other extensionsOverride — full replacement.

The overlay step runs after the MCP and Permissions transpilers. When an overlay uses the .override suffix on a file that those transpilers also produce (e.g., opencode.json, .claude/settings.json, kilo.jsonc), the overlay replaces the entire accumulated file content, including all MCP and Permissions output for that file.

Interpolation in Overlays

Text files with supported extensions (.md, .txt, .json, .jsonc, .jsonl, .xml, .html, .svg, .toml, .yml, .yaml) undergo variable interpolation before merging or copying.

Plugin Merge

When plugins are configured, the overlay step processes files from multiple layers in order:

  1. Plugin layers (in order of declaration in config.yml)
  2. Local project layer (.agloom/overlays/<adapterId>/)

Later layers have higher priority. Each layer's files are interpolated with the layer's own resolved values (per-plugin isolation), then merged with the accumulated state.

Deep Merge Rules

For merge-eligible files:

  • Object keys are merged recursively.
  • Arrays are replaced entirely (use patch operations for fine-grained array control).
  • Scalar values are replaced by the later layer.
  • A null value in the incoming layer removes the key from the result.

Error Handling

If an existing base file (targeted by deep merge) cannot be parsed, the overlay step fails with a LayerMergeError instead of silently overwriting the file. The error includes the file path, format, and the parser's error message with position details. You must fix or remove the invalid file before retrying transpilation.

JSONC files (.jsonc) are parsed by stripping comments first, then running JSON.parse. Comments in base files are not preserved on round-trip — the merged output is always clean JSON. TOML files are parsed and serialized with smol-toml, which maintains stable key order.