# Agloom — full documentation > Transpile canonical agent configurations across AI coding assistants This file concatenates the full text of all documentation pages, intended for ingestion by LLMs. See /llms.txt for an indexed version. --- # Formatting Source: https://docs.agloom.sh/guide/formatting > How to format and lint Markdown, JSON, YAML, and TOML files with agloom format # Formatting This guide teaches you how to format and lint your project's Markdown, JSON, YAML, and TOML files using the built-in `agloom format` command. ## What `agloom format` Does `agloom format` is a wrapper around [prettier](https://prettier.io/) and [markdownlint-cli2](https://github.com/DavidAnson/markdownlint-cli2) that ships with Agloom. It exists so you do not have to install and wire up those tools yourself just to keep your canonical files tidy. The command has two modes: - **Write mode** (default) — formats files in place and applies autofixable lint rules. - **Check mode** (`--check`) — reports unformatted files and lint violations without modifying anything. Exits with code 1 if any file needs attention. Useful for CI. ## Supported File Types | Extension | prettier | markdownlint | | --------------- | -------- | ------------ | | `.md`, `.mdx` | yes | yes | | `.json` | yes | no | | `.yaml`, `.yml` | yes | no | | `.toml` | yes | no | Files with any other extension are silently skipped, even if they match the glob. ## Default File Set When you run `agloom format` with no arguments, it processes: - `.agloom/**/*.{md,mdx,json,yaml,yml,toml}` — everything inside the canonical directory. - `**/AGLOOM.md` — canonical instruction files anywhere in the project. The following directories are always excluded: `node_modules`, `.git`, `dist`, `build`, `coverage`, `.next`, `.turbo`, `.cache`. Files and directories listed in `.gitignore` are also excluded. ## Formatting Extra Directories Positional arguments **replace** the default file set — they do not extend it. To format your `docs/` directory along with the defaults, pass both explicitly: ```bash agloom format ".agloom/**/*.{md,mdx,json,yaml,yml,toml}" "**/AGLOOM.md" "docs/**/*.{md,mdx,json,yaml,yml,toml}" ``` A common pattern is to wrap this in an npm script: ```json title="package.json" { "scripts": { "fmt:md": "agloom format \".agloom/**/*.{md,mdx,json,yaml,yml,toml}\" \"**/AGLOOM.md\" \"docs/**/*.{md,mdx,json,yaml,yml,toml}\"", "fmt:md:check": "agloom format --check \".agloom/**/*.{md,mdx,json,yaml,yml,toml}\" \"**/AGLOOM.md\" \"docs/**/*.{md,mdx,json,yaml,yml,toml}\"" } } ``` If you want to format **every** supported file under the project root, use `--all`: ```bash agloom format --all ``` `--all` cannot be combined with positional arguments. ## Configuration `agloom format` resolves prettier and markdownlint configuration from three layers, in order of increasing priority: 1. **Built-in defaults** — bundled with Agloom, see below. 2. **Native config files** — `.prettierrc.*` and `.markdownlint.*` in the project root. Prettier and markdownlint discover these themselves. 3. **Sections in `.agloom/config.yml`** — `prettier` and `markdownlint` top-level fields. Values are passed to the tools as-is (shallow merge over layers 1 and 2). ### Built-in Defaults Prettier defaults: ```yaml proseWrap: preserve tabWidth: 2 ``` Markdownlint defaults: ```yaml MD007: indent: 2 MD013: false MD024: siblings_only: true MD025: false MD049: style: "underscore" MD050: style: "asterisk" ``` ### Overriding via `.agloom/config.yml` Add `prettier` and `markdownlint` top-level sections to `.agloom/config.yml`: ```yaml title=".agloom/config.yml" prettier: proseWrap: always tabWidth: 4 markdownlint: MD013: line_length: 80 ``` Agloom does not validate the contents of these sections — prettier and markdownlint own their own schemas and will report errors directly if a value is invalid. --- # Getting Started Source: https://docs.agloom.sh/guide/getting-started > From zero to your first transpile in 5 minutes import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; # Getting Started This guide walks you through installing Agloom and running your first transpilation. By the end, you will have a working `.agloom/` directory and generated config files for your AI coding tool. ## Prerequisites - **Node.js 20+** (check with `node -v`) - **npm** or **pnpm** package manager ## Installation Install Agloom globally: ```bash npm install -g agloom ``` Verify the installation: ```bash agloom --version ``` ## Step 1: Initialize Create a `.agloom/config.yml` file in your project root. You can do this manually or use the `init` command. Using `init`: ```bash agloom init --adapter claude ``` This creates a `config.yml` and copies any existing Claude Code files (`CLAUDE.md`, `.claude/`, `.mcp.json`) into `.agloom/overlays/claude/` so they are preserved as overlays. ```bash agloom init --adapter codex ``` This creates a `config.yml` and copies any existing Codex files (`AGENTS.md`, `.codex/`, `.agents/`) into `.agloom/overlays/codex` so they are preserved as overlays. ```bash agloom init --adapter gemini ``` This creates a `config.yml` and copies any existing Gemini files (`GEMINI.md`, `.gemini/`) into `.agloom/overlays/gemini/` so they are preserved as overlays. ```bash agloom init --adapter opencode ``` This creates a `config.yml` and copies any existing OpenCode files (`AGENTS.md`, `.opencode/`, `opencode.json`) into `.agloom/overlays/opencode` so they are preserved as overlays. ```bash agloom init --adapter kilocode ``` This creates a `config.yml` and copies any existing KiloCode files (`AGENTS.md`, `.kilo/`) into `.agloom/overlays/kilocode` so they are preserved as overlays. Or create it manually: ```yaml # .agloom/config.yml adapters: - claude ``` ```yaml # .agloom/config.yml adapters: - codex ``` ```yaml # .agloom/config.yml adapters: - gemini ``` ```yaml # .agloom/config.yml adapters: - opencode ``` ```yaml # .agloom/config.yml adapters: - kilocode ``` The `adapters` field tells Agloom which target tools to generate files for. You can list multiple adapters to generate files for several tools at once. ## Step 2: Write Instructions Create an `AGLOOM.md` file in your project root with your project instructions: ```markdown # My Project ## Stack TypeScript, Node.js, React. ## Conventions - Use functional components. - Write tests for all new features. - Keep functions pure when possible. ``` Agloom discovers `AGLOOM.md` files in the project root and any subdirectories (excluding `node_modules`, hidden directories, and `.gitignore` entries). Each file is transpiled into the corresponding instruction file for every adapter listed in your config. ## Step 3: Transpile Run the transpile command: ```bash agloom transpile ``` Agloom reads your `.agloom/` directory and generates config files for each adapter: Produces a `CLAUDE.md` in your project root. Add `--verbose` to see all steps: ```bash agloom transpile --verbose ``` ```text ✓ Transpiling for claude... ✓ Instructions 1 files ✓ Commands 0 files ✓ Skills 0 files ✓ Agents 0 files ✓ MCP 0 files ✓ Permissions 0 files ✓ Docs 0 files ✓ Schemas 0 files ✓ Overlay 0 files Done. 1 files written. ``` Produces an `AGENTS.md` in your project root (the shared instruction format used by Codex). Add `--verbose` to see all steps: ```bash agloom transpile --verbose ``` ```text ✓ Transpiling for agentsmd... ✓ Instructions 1 files ✓ Overlay 0 files ✓ Transpiling for codex... ✓ Instructions 0 files ✓ Commands 0 files ✓ Skills 0 files ✓ Agents 0 files ✓ Overlay 0 files Done. 1 files written. ``` Produces a `GEMINI.md` in your project root. Add `--verbose` to see all steps: ```bash agloom transpile --verbose ``` ```text ✓ Transpiling for gemini... ✓ Instructions 1 files ✓ Commands 0 files ✓ Skills 0 files ✓ Agents 0 files ✓ Docs 0 files ✓ Schemas 0 files ✓ Overlay 0 files Done. 1 files written. ``` Produces an `AGENTS.md` in your project root (the shared instruction format used by OpenCode). Add `--verbose` to see all steps: ```bash agloom transpile --verbose ``` ```text ✓ Transpiling for agentsmd... ✓ Instructions 1 files ✓ Overlay 0 files ✓ Transpiling for opencode... ✓ Instructions 0 files ✓ Commands 0 files ✓ Skills 0 files ✓ Agents 0 files ✓ MCP 0 files ✓ Permissions 0 files ✓ Docs 0 files ✓ Schemas 0 files ✓ Overlay 0 files Done. 1 files written. ``` Produces an `AGENTS.md` in your project root (the shared instruction format used by KiloCode). Add `--verbose` to see all steps: ```bash agloom transpile --verbose ``` ```text ✓ Transpiling for agentsmd... ✓ Instructions 1 files ✓ Overlay 0 files ✓ Transpiling for kilocode... ✓ Instructions 0 files ✓ Commands 0 files ✓ Skills 0 files ✓ Agents 0 files ✓ Docs 0 files ✓ Schemas 0 files ✓ Overlay 0 files Done. 1 files written ``` ## Step 4: Verify Open the generated `CLAUDE.md` and confirm it contains your instructions. Open the generated `AGENTS.md` and confirm it contains your instructions. Open the generated `GEMINI.md` and confirm it contains your instructions. Open the generated `AGENTS.md` and confirm it contains your instructions. Open the generated `AGENTS.md` and confirm it contains your instructions. ## Formatting Agloom includes a `format` command to format canonical files (Markdown, JSON, YAML, TOML). By default, it targets `.agloom/**/*` and `**/AGLOOM.md`: ```bash agloom format ``` You can pass specific paths or globs, or use `--all` to format all supported files in the project: ```bash agloom format "docs/**/*.md" agloom format --all ``` Use `--check` to verify formatting without modifying files. See [reference/cli](../reference/cli.md) for full details. ## What's Next - Learn about the [project structure](project-structure.md) to understand what goes where in `.agloom/`. - Add [agent-specific instructions](instructions.md) for different tools. - Create reusable [skills and agents](skills-and-agents.md). - Share configurations with [plugins](plugins.md). --- # Instructions Source: https://docs.agloom.sh/guide/instructions > How to write instructions for AI agents with agent-specific blocks # Instructions This guide teaches you how to write instructions for AI coding assistants using the canonical `AGLOOM.md` format. ## What Are Instructions Instructions are `AGLOOM.md` files placed in your project root or any subdirectory. They contain project-level guidance for AI coding assistants — your stack, conventions, boundaries, and workflow preferences. When you run `agloom transpile`, Agloom discovers all `AGLOOM.md` files and transforms each one into agent-specific instruction files (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, etc.) at the same relative path, based on your configured adapters. ## Basic Instructions Start by creating a simple `AGLOOM.md` with content that applies to all agents: ```markdown # My Project ## Stack TypeScript, React, PostgreSQL. ## Conventions - Use functional components with hooks. - All API calls go through the `api/` directory. - Write unit tests for business logic. ## Boundaries - Never modify database migrations directly — use the migration generator. - Never commit `.env` files. ``` Everything in this file (outside of agent-specific blocks) is included in the output for **every** adapter. ## Agent-Specific Blocks Sometimes you need instructions that apply only to a particular tool. Use HTML comment tags to define agent-specific sections: ```markdown # My Project All agents see this content. Use the `Grep` and `Glob` tools for code search instead of shelling out to `grep`/`find`. Run shell commands only when no dedicated tool exists. Use the file search and read tools provided by your environment. Always read a file before editing it. This content is also visible to all agents. ``` When transpiling for Claude, the `agentsmd` block is removed and the `claude` block content is included (without the comment tags). When transpiling for AGENTS.md, the reverse happens. ## Valid Agent IDs Only agents that have their own instruction file format can be used in agent-specific blocks: | Agent ID | Instruction file | Can use in blocks | | ---------- | ---------------- | ----------------- | | `claude` | `CLAUDE.md` | Yes | | `agentsmd` | `AGENTS.md` | Yes | | `gemini` | `GEMINI.md` | Yes | | `opencode` | _(none)_ | No | | `kilocode` | _(none)_ | No | | `codex` | _(none)_ | No | `opencode`, `kilocode`, and `codex` do not have their own instruction file format — they use `AGENTS.md` (generated by the `agentsmd` adapter). To write content specific to these tools, use `` blocks. Using an invalid agent ID in a block (e.g., ``) will cause a transpilation error. ## Multiple Instruction Files Agloom supports instruction files in subdirectories. If you place an `AGLOOM.md` in a subdirectory (e.g., `src/AGLOOM.md`), it will be transpiled to the corresponding location (e.g., `src/CLAUDE.md` for the Claude adapter). This lets you provide directory-level instructions that agents pick up when working in specific parts of your codebase. ## Example Here is a complete `AGLOOM.md` with shared and agent-specific sections. ```markdown --- description: Main project instructions --- # My Web App ## Stack TypeScript, Next.js 14, Prisma, PostgreSQL. ## Commands - Build: `pnpm run build` - Test: `pnpm run test` - Lint: `pnpm run lint` ## Conventions - Use server components by default. - Client components must have the `"use client"` directive. - All database queries go through Prisma — never write raw SQL. - Tests live next to source as `*.spec.ts`, not in a separate `__tests__` tree. ## Claude Code workflow - For non-trivial features, draft a plan with the `ExitPlanMode` tool before writing code. The plan must list the files you intend to touch. - Track multi-step work with `TaskCreate` / `TaskUpdate`. Mark each task completed as you finish it, not in batches at the end. - For independent investigations (e.g. "is X used anywhere?"), spawn the`Explore` subagent in parallel rather than running searches sequentially in the main thread. - Prefer dedicated tools over Bash: `Read` over `cat`, `Grep` over `grep`, `Glob` over `find`, `Edit` over `sed`. ## AGENTS.md workflow - Read the relevant file fully before editing it; do not patch based on a partial view. - After every meaningful change, run `pnpm run test` and address failures before moving on. - For multi-file changes, write a short outline of the planned edits at the top of your response so the user can interrupt early if the direction is wrong. ## Boundaries - Never modify files in `generated/` — they are produced by `prisma generate`. - Never skip TypeScript strict mode or use `// @ts-ignore`. - Never commit `.env*` files; use `.env.example` for documenting variables. ``` The YAML frontmatter is optional. If present, it can contain an `override` block for adapter-specific frontmatter fields. See [reference/transpilers](../reference/transpilers.md) for details on frontmatter overrides. --- # Introduction Source: https://docs.agloom.sh/ > What Agloom does, why it exists, and when to use it # Introduction ## The Problem AI coding assistants are becoming an essential part of the development workflow. Claude Code, OpenCode, Codex, KiloCode, Gemini, and others each bring unique capabilities to the table. But they also bring unique configuration formats: - Claude Code reads `CLAUDE.md` and `.claude/` - OpenCode reads `AGENTS.md` and `.opencode/` - Codex reads `AGENTS.md` and `.codex/` - KiloCode reads `AGENTS.md` and `.kilo/` - Gemini reads `GEMINI.md` and `.gemini/` Maintaining separate config files for each assistant is tedious and error-prone. Instructions drift apart, skills get duplicated, and there is no single source of truth for how your project should be understood by AI agents. ## The Solution Agloom introduces a **canonical format** — a single `.agloom/` directory that holds all your instructions, skills, agent definitions, docs, and schemas. When you run `agloom transpile`, it generates the correct config files for each target assistant. Think of it like Sass compiling to CSS, or TypeScript compiling to JavaScript. You write once, and Agloom produces the right output for each tool. ```text AGLOOM.md --> CLAUDE.md, AGENTS.md, GEMINI.md .agloom/ config.yml (project configuration) skills/ --> .claude/skills/, .opencode/skills/, ... agents/ --> .claude/agents/, .opencode/agents/, ... docs/ --> .claude/docs/, .opencode/docs/, ... mcp.yml --> .mcp.json, opencode.json (mcp section) permissions.yml --> .claude/settings.json, opencode.json (permissions) ``` ## Core Principles **Single source of truth.** One `.agloom/` directory, multiple outputs. Edit your instructions in one place and let Agloom keep everything in sync. **Adapter-driven.** Each target tool is supported by an adapter. Adapters know how to transform canonical files into the format their tool expects. Agloom ships with adapters for Claude Code, OpenCode, Codex, KiloCode, and Gemini. **Plugin-extensible.** Package your skills, agents, docs, and schemas into plugins and reuse them across projects. Plugins can be loaded from local directories or git repositories. **Non-intrusive.** Agloom generates files but does not interfere with how target tools work. The generated files are standard config files that each tool reads natively. **Project-scoped.** Agloom only reads from and writes to your project directory. It never touches global or home-directory configuration like `~/.claude/`, `~/.codex/`, or `~/.config/gemini/`. Your personal preferences and machine-wide tool settings stay completely out of scope — switching to Agloom in one project does not affect any other project or your global setup. ## Key Features **Agent-specific blocks.** Use `` and `` HTML comments to include content that only applies to a specific agent. Shared content lives outside these blocks and reaches all agents. **Frontmatter overrides.** YAML frontmatter in markdown files supports an `override` block where you can set agent-specific metadata, such as a model selection. **Variable interpolation.** Reference environment variables (`${env:API_KEY}`), dir paths (`${agloom:SKILLS_DIR}`), and plugin values (`${values:name}`) anywhere in your canonical files. Values are resolved at transpile time. **Overlays.** Place raw files in `.agloom/overlays//` for content that does not fit the canonical format — agent-specific JSON settings, TOML configs, or any file the target tool expects. Overlays support deep merge, full replacement, and patch operations. ## When to Use Agloom Agloom is a good fit when: - Your project uses **two or more** AI coding assistants. - Your team wants to **standardize** instructions and conventions across agents. - You have **reusable skills or agents** that should be shared between projects. - You want a **plugin system** to distribute team-wide configurations. ## When NOT to Use Agloom Agloom may not be worth the overhead when: - Your project uses **only one** AI coding assistant, and you have no plans to add others. - You have no need for plugins or shared configurations. In that case, editing the tool's native config files directly is simpler. ## What's Next - **[Getting Started](./getting-started.md)** — Install Agloom and run your first transpile in five minutes. - **[Project Structure](./project-structure.md)** — Tour the anatomy of the `.agloom/` directory and the files it produces. - **[Instructions](./instructions.md)** — Write canonical `AGLOOM.md` files with agent-specific blocks. - **[Skills and Agents](./skills-and-agents.md)** — Define reusable skills and sub-agent definitions once, ship them everywhere. - **[Variables and Interpolation](./variables.md)** — Reference environment variables, project paths, and plugin values from canonical files. - **[Plugins](./plugins.md)** — Package and share configurations across projects. - **[Formatting](./formatting.md)** — Format and lint Markdown, JSON, YAML, and TOML files via `agloom format`. --- # Overlays Source: https://docs.agloom.sh/guide/overlays > How to use overlays for adapter-specific file customization # Overlays This guide teaches you how to use overlays to add adapter-specific files that do not fit the canonical format. ## What Are Overlays Overlays are raw files placed in `.agloom/overlays//`. After transpilation, these files are copied to the project root, preserving their relative path within the overlay directory. Overlays run **after** all transpiler steps (instructions, skills, agents, docs, schemas). If an overlay file has the same path as a transpiled file, the overlay takes precedence. ## When to Use Overlays Use overlays for adapter-specific configuration files that Agloom does not generate through its canonical format: - Claude Code settings (`settings.json`) - Claude Code only slash commands - MCP configuration overlays - OpenCode configuration files - Any tool-specific config that needs to be in a specific format ## Example To add a Claude Code `settings.json`, create the overlay file: ```text .agloom/overlays/claude/.claude/settings.json ``` ```json { "permissions": { "allow": ["Bash(npm run *)"], "deny": ["Bash(rm -rf *)"] } } ``` When you run `agloom transpile`, this file is copied to `.claude/settings.json` in your project root. Another example — a Claude Code slash command: ```text .agloom/overlays/claude/.claude/commands/deploy.md ``` This copies to `.claude/commands/deploy.md` after transpilation. ## File Merge Strategies When an overlay file targets a path that already has content from a previous layer (e.g., a plugin), the merge strategy depends on the file format: **Deep merge** applies to structured file formats: - `.json`, `.jsonc` - `.yaml`, `.yml` - `.toml` For these formats, Agloom performs a deep merge — objects are merged recursively, and arrays are replaced. **Full replacement** applies to everything else (`.md`, `.txt`, images, etc.). The overlay file completely replaces the existing file. ## Suffix Modifiers Two special suffixes let you control the merge behavior: ### `.override` — Force Replacement Add `.override` before the file extension to force full replacement, even for merge-eligible formats: ```text .agloom/overlays/claude/.claude/settings.override.json ``` This replaces the entire `settings.json` instead of deep-merging it. ### `.patch` — Patch Operations Add `.patch` before the file extension to apply fine-grained modifications: ```text .agloom/overlays/claude/.claude/settings.patch.json ``` Patch files contain declarative operations that modify specific parts of the target file: ```json { "permissions": { "allow": { "$append": ["Bash(docker *)"] } } } ``` This appends `"Bash(docker *)"` to the `permissions.allow` array without replacing the entire file or array. Available patch operations: `$set`, `$merge`, `$append`, `$prepend`, `$remove`, `$unset`, `$mergeBy`, `$insertAt`. See [reference/patch-operations](../reference/patch-operations.md) for the full list of operations with examples. ## Interpolation in Overlays Overlay files with certain extensions (`.md`, `.txt`, `.json`, `.jsonc`, `.jsonl`, `.xml`, `.html`, `.svg`, `.toml`, `.yml`, `.yaml`) go through variable interpolation before being written. You can use `${agloom:VAR}`, `${env:VAR}`, and `${values:VAR}` in these files. Binary files and files with other extensions are copied as-is. See [Variables](variables.md) for more on interpolation. --- # Plugins Source: https://docs.agloom.sh/guide/plugins > How to use and create plugins for sharing configurations # Plugins This guide teaches you how to use existing plugins and create your own. ## What Are Plugins Plugins are reusable packages of skills, agents, docs, schemas, instructions, and overlays. They let you share AI agent configurations across projects. A plugin is a directory containing a `plugin.yml` manifest and an `.agloom/`-like structure. Plugins can be loaded from local paths or git repositories. ## Using a Plugin Add plugins to the `plugins` section of your `.agloom/config.yml`. ### From a Git Repository Use a git URL (SSH or HTTPS): ```yaml title=".agloom/config.yml" adapters: - claude plugins: - git@github.com:user/my-plugin - https://github.com/user/another-plugin ``` You can pin a specific ref (branch, tag, or commit) and point to a subdirectory within the repo: ```yaml title=".agloom/config.yml" plugins: - git@github.com:user/my-plugin#v1.0.0 - git@github.com:user/monorepo#main//packages/agloom-plugin ``` The `#ref` suffix specifies the git ref. The `//path` suffix specifies a subdirectory within the repository. ### From a Local Path Use a relative path: ```yaml title=".agloom/config.yml" plugins: - ../shared-plugin ``` ### Object Form For more control, use the object form: ```yaml title=".agloom/config.yml" plugins: - git: git@github.com:user/my-plugin ref: v1.0.0 path: subdir values: team_name: "platform" api_token: "${env:API_TOKEN}" - path: ../local-plugin values: feature_flag: "true" ``` The object form lets you specify `ref`, `path`, and `values` (see below). ## Plugin Values Plugins can declare variables that consumers must (or may) provide. Values are passed through the `values` field in the plugin entry. For example, if a plugin declares a `team_name` variable: ```yaml title="plugin.yml" variables: team_name: description: "Team name for commit messages" required: true ``` You provide the value in your config: ```yaml title=".agloom/config.yml" plugins: - git: git@github.com:user/team-plugin values: team_name: "platform" ``` Values can reference environment variables using `${env:VAR}`: ```yaml title=".agloom/config.yml" plugins: - git: git@github.com:user/team-plugin values: team_name: "platform" api_token: "${env:TEAM_API_TOKEN}" ``` Sensitive variables (declared with `sensitive: true` in the plugin manifest) **must** use `${env:VAR}` — inline values are rejected to prevent accidental commits of secrets. See [Variables](variables.md) for more on how interpolation works. ## Creating a Plugin Step 1: Create a directory with a `plugin.yml` manifest: ```yaml title="my-plugin/plugin.yml" name: my-plugin version: 1.0.0 description: "Shared coding conventions for our team" author: name: "Jane Doe" email: "jane@example.com" ``` Step 2: Add content using the same structure as `.agloom/`: ```title="my-plugin structure" my-plugin/ ├── plugin.yml ├── skills/ │ └── code-review/ │ └── SKILL.md ├── agents/ │ └── reviewer.md └── overlays/ └── claude/ └── .claude/ └── settings.json ``` Step 3: Optionally declare variables: ```yaml title="my-plugin/plugin.yml" name: my-plugin version: 1.0.0 description: "Shared coding conventions" author: name: "Jane Doe" variables: team_name: description: "Team name" required: true slack_channel: description: "Slack channel for notifications" default: "#engineering" ``` See [reference/plugin-manifest](../reference/plugin-manifest.md) for the full manifest format. ## Plugin Caching Git plugins are cached locally in `~/.agloom/cache/plugins/`. On subsequent transpile runs, Agloom uses the cached version instead of cloning again. To force a fresh clone: ```bash agloom transpile --refresh ``` To clear the entire cache: ```bash agloom cache clean ``` ## How Plugins Merge Plugins go through the same transpilation pipeline as your local `.agloom/` content. Their instructions, skills, agents, docs, schemas, and overlays are merged into the final output. The merge order follows the plugin declaration order in `config.yml`. Plugins listed first have lower priority — later plugins and the local project can override earlier ones. The local project always has the highest priority. --- # Project Structure Source: https://docs.agloom.sh/guide/project-structure > Anatomy of the .agloom/ directory and generated output files # Project Structure This guide explains the layout of the `.agloom/` directory and how it maps to generated output files. ## Canonical Directory The `.agloom/` directory is the single source of truth for your project's AI agent configuration. Here is the full structure: ```text .agloom/ ├── agents/ # Sub-agent definitions │ └── reviewer.md ├── commands/ # Slash-command definitions │ ├── deploy.md │ └── git/ │ └── commit.md ├── docs/ # Documentation files for agents ├── schemas/ # JSON/OpenAPI schemas for other files ├── skills/ # Reusable skill definitions │ └── my-skill/ │ ├── SKILL.md │ └── helpers.ts ├── config.yml # Project configuration (adapters, plugins, variables) ├── mcp.yml # MCP server configuration ├── permissions.yml # Agent permissions ├── overlays/ # Per-adapter overrides │ ├── claude/ │ └── opencode/ └── AGLOOM.md # Instructions for AI agents ``` ### What Each Part Does **`config.yml`** — project configuration. Lists which adapters to use, which plugins to load, and project-level variables. **`AGLOOM.md`** — top-level `AGLOOM.md` file, the canonical instructions file. This is where you write project conventions, stack descriptions, and coding guidelines that AI agents should follow. **`skills/`** — reusable action definitions. Each skill is a directory containing a `SKILL.md` file and any supporting files. Skills are copied to each agent's skill directory during transpilation. **`agents/`** — sub-agent definitions. Each agent is a single `.md` file with YAML frontmatter describing the agent's role, model, and tools. **`commands/`** — slash-command definitions. Each command is a single `.md` file with YAML frontmatter and a Markdown body. Commands may be organized into subdirectories (e.g., `commands/git/commit.md`). During transpilation, commands are transformed and written to each agent's commands directory. See [Skills and Agents](skills-and-agents.md) for details on creating commands. **`docs/`** — documentation files that agents can reference. Copied to each agent's docs directory. **`schemas/`** — JSON or OpenAPI schema files. Copied to each agent's schemas directory. **`mcp.yml`** — MCP (Model Context Protocol) server configuration. Transpiled into agent-specific formats (`.mcp.json` for Claude, `opencode.json` for OpenCode). See [reference/transpilers](../reference/transpilers.md) for details. **`permissions.yml`** — agent permissions configuration. Transpiled into agent-specific formats. See [reference/transpilers](../reference/transpilers.md) for details. **`overlays/`** — per-agent override files. Files placed here are copied directly to the project root after transpilation. Use overlays for agent-specific config that does not fit the canonical format. See [Overlays](overlays.md) for details. ## Generated Files Each adapter generates different output files. Here is what you get: | Adapter | Generated files | | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `claude` | `CLAUDE.md`, `.claude/agents/`, `.claude/commands/`, `.claude/docs/`, `.claude/schemas/`, `.claude/skills/`, `.claude/settings.json`, `.mcp.json` | | `codex` | `AGENTS.md`, `.agents/skills/`, `.codex/agents/`, `.codex/docs/`, `.codex/schemas/`, | | `gemini` | `GEMINI.md`, `.gemini/agents/`, `.gemini/commands/`, `.gemini/docs/`, `.gemini/schemas/`, `.gemini/skills/` | | `opencode` | `AGENTS.md`, `.opencode/agents/`, `.opencode/commands/`, `.opencode/docs/`, `.opencode/schemas/`, `.opencode/skills/`, `opencode.json` | | `kilocode` | `AGENTS.md`, `.kilo/agents/`, `.kilo/commands/`, `.kilo/docs/`, `.kilo/schemas/`, `.kilo/skills/`, `kilo.json` | | `agentsmd` | `AGENTS.md` (generated automatically as a dependency) | Note that `agentsmd` is a hidden adapter — you do not configure it directly. It is included automatically when you use `opencode`, `kilocode`, or `codex` (which depend on it for `AGENTS.md` generation). ## Important Rule **Never edit generated files directly.** Always edit the canonical files in `.agloom/` and run `agloom transpile`. Generated files are overwritten on every transpile run. ## .gitignore It is recommended to **commit** the `.agloom/` directory to version control and **add generated files** to `.gitignore`: ```gitignore # Agloom (local instructions) AGLOOM.override.md # AGENTS.md generated AGENTS.md AGENTS.override.md !.agloom/**/AGENTS # Claude Code generated .claude/ .mcp.json CLAUDE.md !.agloom/**/.claude !.agloom/**/.mcp.json !.agloom/**/CALUDE.md # Codex generated .agents/ .codex/ !.agloom/**/.agents !.agloom/**/.codex # Gemini generated .gemini/ GEMINI.md !.agloom/**/.gemini !.agloom/**/GEMINI.md # OpenCode generated .opencode/ opencode.json opencode.jsonс !.agloom/**/.opencode !.agloom/**/opencode.json !.agloom/**/opencode.jsonс # KiloCode generated .kilo/ kilo.json kilo.jsonc !.agloom/**/.kilo !.agloom/**/kilo.json !.agloom/**/kilo.jsonc ``` This way, your team shares the canonical source and each developer generates output locally. --- # Skills and Agents Source: https://docs.agloom.sh/guide/skills-and-agents > How to create reusable skills and sub-agent definitions # Skills and Agents This guide teaches you how to create skills (reusable actions) and agents (sub-agent definitions) in Agloom. ## What Are Skills Skills are reusable action definitions stored in `.agloom/skills/`. Each skill is a directory containing a `SKILL.md` file and any number of supporting files (helpers, templates, data). During transpilation, skill directories are copied to each adapter's skill directory (e.g., `.claude/skills/`, `.opencode/skills/`). ## Creating a Skill Step 1: Create a skill directory: ```bash mkdir -p .agloom/skills/code-review ``` Step 2: Create the `SKILL.md` file with YAML frontmatter and a Markdown body: ```markdown --- name: code-review description: Reviews code changes for quality and conventions --- # Code Review Review the provided code changes for: 1. Correctness — does the code do what it claims? 2. Style — does it follow project conventions? 3. Tests — are new features covered by tests? 4. Security — are there any obvious vulnerabilities? Provide feedback as a numbered list of findings. ``` Markdown files inside a skill package (`SKILL.md` and any supporting `.md` files) support variable interpolation, agent-specific blocks, and a frontmatter `override` block for per-adapter customization. Step 3: Optionally add supporting files: ```text .agloom/skills/code-review/ ├── SKILL.md ├── checklist.md └── examples/ └── good-review.md ``` All files in the skill directory are copied to the output. Step 4: Run `agloom transpile`. The skill appears in each adapter's directory: ```text .claude/skills/code-review/SKILL.md .claude/skills/code-review/checklist.md .claude/skills/code-review/examples/good-review.md .opencode/skills/code-review/SKILL.md ... ``` ## What Are Agents Agents are sub-agent definitions stored in `.agloom/agents/`. Each agent is a single `.md` file with YAML frontmatter describing the agent's role, model, and available tools. During transpilation, agent files are transformed (frontmatter overrides are applied, agent-specific blocks are filtered) and written to each adapter's agents directory. ## Creating an Agent Step 1: Create an agent file at `.agloom/agents/reviewer.md`: ```markdown --- name: code-reviewer description: Reviews code for best practices model: sonnet tools: - Read - Grep - Glob override: opencode: model: anthropic/claude-sonnet-4-5 temperature: 0.1 --- You are a code reviewer. Analyze the provided code and report issues related to correctness, performance, and maintainability. Focus on actionable feedback. Do not nitpick style issues that a linter would catch. ``` The `override` block lets you customize frontmatter fields per adapter. In this example, when transpiling for OpenCode, the `model` field is replaced with `anthropic/claude-sonnet-4-5` and `temperature: 0.1` is added. The `override` key itself is removed from the output. Step 2: Run `agloom transpile`. The agent file appears in each adapter's directory: ```text .claude/agents/reviewer.md .opencode/agents/reviewer.md ``` Each output file has adapter-specific frontmatter applied. ## What Are Commands Commands are slash-command definitions stored in `.agloom/commands/`. Each command is a single `.md` file with YAML frontmatter and a Markdown body. Unlike skills (which are directories), a command is a single file. Commands may be organized into subdirectories. For example, you can group git-related commands under `commands/git/`. ## Creating a Command Step 1: Create a command file at `.agloom/commands/deploy.md`: ```markdown --- description: Deploy to production --- Deploy the current branch to production environment. Verify all tests pass before deploying. ``` The frontmatter fields are passed through to each adapter. Agloom does not validate or interpret command-specific fields like `description` — the target agent defines what fields are meaningful. Step 2: Run `agloom transpile`. The command appears in each adapter's commands directory: ```text .claude/commands/deploy.md .gemini/commands/deploy.toml .kilo/commands/deploy.md .opencode/commands/deploy.md ``` Note that Gemini receives a `.toml` file (converted automatically) and Codex receives a skill package in `.agents/skills/deploy/SKILL.md` (since Codex does not support commands natively). ### Commands in Subdirectories You can organize commands into subdirectories: ```text .agloom/commands/ ├── deploy.md └── git/ ├── commit.md └── push.md ``` Some adapters **preserve** the subdirectory structure (Claude, Gemini), while others **flatten** it (OpenCode, KiloCode, Codex): - Preserve: `.agloom/commands/git/commit.md` becomes `.claude/commands/git/commit.md` - Flatten: `.agloom/commands/git/commit.md` becomes `.opencode/commands/commit.md` When flattening, if two commands from different subdirectories have the same filename, transpilation fails with a name conflict error. ### Frontmatter Override Like agents, commands support per-adapter frontmatter overrides: ```markdown --- description: Deploy to production override: gemini: description: Deploy the app to production claude: argument-hint: "[environment]" --- Deploy the current branch. ``` The `override` block merges adapter-specific fields into the frontmatter for each target. The `override` key itself is removed from the output. See [reference/transpilers](../reference/transpilers.md) for details on the commands transpiler. ### Agent-Specific Sections The body may contain agent-specific sections, just like agent definitions: ```markdown --- description: Deploy to production --- Deploy the current branch to production. Use the Bash tool to run deployment scripts. Use !{deploy.sh} to deploy. ``` Content outside sections appears in all outputs. Matching sections are unwrapped; non-matching sections are removed. ## Adapter Support Not all adapters support skills, agents, and commands: | Adapter | Skills | Agents | Commands | | ---------- | ------ | ------ | --------------- | | `claude` | Yes | Yes | Yes | | `codex` | Yes | Yes | Yes (as skills) | | `gemini` | Yes | Yes | Yes (TOML) | | `opencode` | Yes | Yes | Yes | | `kilocode` | Yes | Yes | Yes | | `agentsmd` | No | No | No | The `agentsmd` adapter only handles instruction files (`AGENTS.md`). It does not have its own skills, agents, or commands directories. The `codex` adapter converts commands into skill packages (`.agents/skills//SKILL.md`) since Codex does not support commands natively. The `gemini` adapter converts commands from Markdown to TOML format. ## Example Here is a realistic skill and agent working together. **Skill** — `.agloom/skills/spec-review/SKILL.md`: ```markdown --- name: spec-review description: Review a specification document for completeness --- # Spec Review Given a specification document, check for: 1. All operations have defined inputs and outputs. 2. Error cases are documented with specific error messages. 3. No ambiguous language (look for "TBD", "TODO", "FIXME"). 4. Cross-references to other specs are valid. Output a checklist with pass/fail for each criterion. ``` **Agent** — `.agloom/agents/spec-reviewer.md`: ```markdown --- name: spec-reviewer description: Reviews specification documents model: sonnet tools: - Read - Glob - Grep --- You are a specification reviewer. Use the spec-review skill to analyze documents in the `docs/specs/` directory. Read each spec file, apply the review checklist, and produce a summary report. ``` --- # Variables and Interpolation Source: https://docs.agloom.sh/guide/variables > How to use variables and interpolation in canonical files # Variables and Interpolation This guide teaches you how to use variables for dynamic content in your canonical files. ## What Is Interpolation Interpolation is the substitution of variable references with their values during transpilation. When Agloom encounters a pattern like `${agloom:VAR}` in your files, it replaces it with the actual value before writing the output. ## Variable Namespaces Agloom supports three variable namespaces: ### `${agloom:VAR}` — Agloom Variables These are adapter-dependent path variables. They resolve to different values depending on which adapter is being transpiled. **Dynamic variables** resolve to directories of the adapter currently being transpiled: | Variable | Example (Claude) | | -------------- | ------------------ | | `SKILLS_DIR` | `.claude/skills` | | `AGENTS_DIR` | `.claude/agents` | | `COMMANDS_DIR` | `.claude/commands` | | `DOCS_DIR` | `.claude/docs` | | `SCHEMAS_DIR` | `.claude/schemas` | Each adapter owns a different set of directories, so a dynamic variable is only available when the current adapter defines it. For instance, `${agloom:COMMANDS_DIR}` is undefined when transpiling for Codex, because Codex has no project-level commands directory. Referencing an undefined variable fails transpilation. **Canonical variables** (fixed, do not change per adapter): | Variable | Value | | -------------------- | ----------------------------- | | `PROJECT_DIR` | Absolute path to 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 that contains an absolute path. All other canonical variables contain paths relative to the project root. You can compose absolute paths by concatenating `${agloom:PROJECT_DIR}` with any relative variable, for example `${agloom:PROJECT_DIR}/${agloom:AGLOOM_DIR}` expands to `/.agloom`. **Per-adapter variables** address another adapter's directories regardless of which adapter is currently being transpiled. Their names follow the pattern `{ADAPTER}__DIR`, where `{ADAPTER}` is the uppercased adapter id: ```markdown ${agloom:CLAUDE_SKILLS_DIR} → .claude/skills ${agloom:OPENCODE_AGENTS_DIR} → .opencode/agents ${agloom:GEMINI_COMMANDS_DIR} → .gemini/commands ``` Each adapter generates the prefixed variables only for the directories it owns. Two exceptions are worth remembering: `CODEX_COMMANDS_DIR` does not exist (Codex has no commands directory), and the `agentsmd` adapter generates no per-adapter variables at all because it owns no directory of its own — it only emits an `AGENTS.md` file. For the complete list of paths per adapter, see [reference/adapters](../reference/adapters.md). Example usage in an agent file: ```markdown Read the protocol at `${agloom:DOCS_DIR}/protocol.md`. Skills are located at `${agloom:SKILLS_DIR}/`. ``` When transpiling for Claude, this becomes: ```markdown Read the protocol at `.claude/docs/protocol.md`. Skills are located at `.claude/skills/`. ``` ### `${env:VAR}` — Environment Variables Reference environment variables from `process.env`: ```markdown Project: ${env:PROJECT_NAME} API endpoint: ${env:API_URL} ``` Agloom automatically loads a `.env` file from your project root (if it exists) before transpilation. Variables defined in `process.env` take precedence over `.env` values. If the referenced variable is not defined, transpilation fails with an error. ### `${values:VAR}` — Plugin and Project Values Reference resolved values from plugins or project variables: ```markdown Team: ${values:team_name} Base URL: ${values:base_url} ``` These values come from two sources: 1. **Plugin values** — resolved from plugin variable declarations and the `values` field in your config (see [Plugins](plugins.md)). 2. **Project variables** — resolved from the `variables` section of `config.yml` (see below). Each plugin receives only its own resolved values — plugins cannot access each other's values. ## Project Variables Declare project-level variables in the `variables` section of `config.yml`: ```yaml title=".agloom/config.yml" adapters: - claude variables: project_name: "${env:PROJECT_NAME}" team: description: "Team name" default: "platform" api_key: description: "API key for external service" default: "${env:API_KEY}" sensitive: true required: true ``` ### Shorthand Form A string value is shorthand for `{ default: "" }`: ```yaml variables: project_name: "${env:PROJECT_NAME}" ``` This is equivalent to: ```yaml variables: project_name: default: "${env:PROJECT_NAME}" ``` ### Full Form The full form supports these fields: - `description` — human-readable description (optional in config, required in plugin manifests). - `default` — default value. Can contain `${env:VAR}` references. - `required` — if `true`, the variable must have a value (from default or environment). Defaults to `false`. - `sensitive` — if `true`, the value must reference an environment variable (`${env:VAR}`). Inline values are rejected. Defaults to `false`. ## .env File Agloom loads a `.env` file from the project root before transpilation. This file follows the standard `dotenv` format: ```bash title=".env" PROJECT_NAME=my-app API_KEY=secret-key-123 ``` Variables from `.env` are available through `${env:VAR}` in instructions, skills, agents, overlays, and variable defaults. If `.env` does not exist, Agloom silently continues without it. ## Where Interpolation Applies Interpolation runs in the following contexts: - **Instructions** — `AGLOOM.md` files (`.md`) - **Skills** — `.md` files within skill directories - **Agents** — `.md` agent definition files - **Docs** — `.md` files in the docs directory - **Schemas** — `.md` files in the schemas directory - **Overlays** — files with interpolatable extensions: `.md`, `.txt`, `.json`, `.jsonc`, `.jsonl`, `.xml`, `.html`, `.svg`, `.toml`, `.yml`, `.yaml` Binary files and non-interpolatable extensions are always copied as-is. ## Escaping To include a literal `${agloom:VAR}` in your output (without interpolation), prefix with a backslash: ```markdown Use \${agloom:SKILLS_DIR} to reference the skills directory. ``` This outputs the literal text `${agloom:SKILLS_DIR}`. ## Example Here is an end-to-end example: declaring a variable in config, using it in a skill, and seeing the result after transpile. **Step 1:** Declare the variable in `config.yml`: ```yaml title=".agloom/config.yml" adapters: - claude variables: team_name: "platform" ``` **Step 2:** Use it in a skill: ```markdown title=".agloom/skills/deploy/SKILL.md" --- name: deploy description: Deploy the application --- # Deploy Deploy the application for the ${values:team_name} team. Artifacts are stored in `${agloom:DOCS_DIR}/deployments/`. ``` **Step 3:** Run `agloom transpile`. The output in `.claude/skills/deploy/SKILL.md`: ```markdown title=".claude/skills/deploy/SKILL.md" --- name: deploy description: Deploy the application --- # Deploy Deploy the application for the platform team. Artifacts are stored in `.claude/docs/deployments/`. ``` The `${values:team_name}` was replaced with `"platform"` and `${agloom:DOCS_DIR}` was replaced with `.claude/docs`. --- # Adapters Source: https://docs.agloom.sh/reference/adapters > Reference for all available adapters, capabilities, and dependencies # Adapters Adapters define how Agloom transpiles canonical configurations into agent-specific files. Each adapter targets a specific AI coding assistant. ## Adapter Table | ID | Description | Output Files | Hidden | | ---------- | ------------------------------------------ | --------------------------------- | ------ | | `claude` | Claude Code | `CLAUDE.md`, `.mcp.json` | No | | `opencode` | OpenCode | `opencode.json` | No | | `agentsmd` | AGENTS.md (Codex, OpenCode, KiloCode, ...) | `AGENTS.md`, `AGENTS.override.md` | Yes | | `kilocode` | KiloCode | _(none)_ | No | | `codex` | Codex (OpenAI) | _(none)_ | No | | `gemini` | Gemini (Google) | `GEMINI.md` | No | ## Per-Adapter Details ### claude - **Instructions file:** `CLAUDE.md` - **Dependencies:** None - **Output paths:** | Type | Path | | -------- | ------------------ | | Skills | `.claude/skills` | | Agents | `.claude/agents` | | Commands | `.claude/commands` | | Docs | `.claude/docs` | | Schemas | `.claude/schemas` | - **Target files:** `CLAUDE.md`, `.mcp.json` - **Overlay import paths:** `.claude`, `**/CLAUDE.md`, `.mcp.json` ### opencode - **Instructions file:** None (uses `AGENTS.md` via `agentsmd` dependency) - **Dependencies:** `agentsmd` - **Output paths:** | Type | Path | | -------- | -------------------- | | Skills | `.opencode/skills` | | Agents | `.opencode/agents` | | Commands | `.opencode/commands` | | Docs | `.opencode/docs` | | Schemas | `.opencode/schemas` | - **Target files:** `opencode.json` - **Overlay import paths:** `.opencode`, `opencode.json` OpenCode does not have its own instruction file format. The `AGENTS.md` file is generated by the `agentsmd` adapter, which is automatically included as a dependency. ### agentsmd - **Instructions file:** `AGENTS.md` - **Dependencies:** None - **Output paths:** _(none — empty paths object)_ - **Target files:** `AGENTS.md`, `AGENTS.override.md` - **Overlay import paths:** `.agents`, `**/AGENTS.md`, `**/AGENTS.override.md` - **Hidden:** Yes — cannot be specified in config or via `--adapter`. Included only as a dependency of other adapters or when using `--all`. The `agentsmd` adapter produces the `AGENTS.md` format used by multiple AI coding assistants (OpenCode, KiloCode, Codex, and others). ### kilocode - **Instructions file:** None (uses `AGENTS.md` via `agentsmd` dependency) - **Dependencies:** `agentsmd` - **Output paths:** | Type | Path | | -------- | ---------------- | | Skills | `.kilo/skills` | | Agents | `.kilo/agents` | | Commands | `.kilo/commands` | | Docs | `.kilo/docs` | | Schemas | `.kilo/schemas` | - **Target files:** _(none)_ - **Overlay import paths:** `.kilo` ### codex - **Instructions file:** None (uses `AGENTS.md` via `agentsmd` dependency) - **Dependencies:** `agentsmd` - **Output paths:** | Type | Path | | ------ | ---------------- | | Skills | `.agents/skills` | | Agents | `.codex/agents` | Note: Codex places skills in `.agents/skills/` (not `.codex/skills/`). - **Target files:** _(none)_ - **Overlay import paths:** `.codex`, `.agents` ### gemini - **Instructions file:** `GEMINI.md` - **Dependencies:** None - **Output paths:** | Type | Path | | -------- | ------------------ | | Skills | `.gemini/skills` | | Agents | `.gemini/agents` | | Commands | `.gemini/commands` | | Docs | `.gemini/docs` | | Schemas | `.gemini/schemas` | - **Target files:** `GEMINI.md` - **Overlay import paths:** `.gemini`, `**/GEMINI.md` ## Capability Matrix | Feature | claude | opencode | agentsmd | kilocode | codex | gemini | | ------------ | ------ | -------- | -------- | -------- | --------------- | ---------- | | Instructions | Yes | No-op | Yes | No-op | No-op | Yes | | Commands | Yes | Yes | No | Yes | Yes (as skills) | Yes (TOML) | | Skills | Yes | Yes | No | Yes | Yes | Yes | | Agents | Yes | Yes | No | Yes | Yes | Yes | | Docs | Yes | Yes | No | Yes | Yes | Yes | | Schemas | Yes | Yes | No | Yes | Yes | Yes | | MCP | Yes | Yes | No | No | No | No | | Permissions | Yes | Yes | No | No | No | No | | Overlays | Yes | Yes | Yes | Yes | Yes | Yes | Adapters marked "No-op" for Instructions return an empty array — their instruction files are generated by a dependency adapter (typically `agentsmd`). Adapters marked "No" for Skills/Agents have an empty `paths` object and do not produce skill or agent directories. For Commands: Codex converts commands into skill packages at `.agents/skills/`. Gemini converts commands from Markdown to TOML format. See [Transpilers](transpilers.md) for full details on the commands transpiler. ## Dependencies Dependencies are resolved automatically. When you specify an adapter (via config or `--adapter`), its dependencies are included before it in topological order. | Adapter | Depends On | | ---------- | ---------- | | `claude` | _(none)_ | | `opencode` | `agentsmd` | | `agentsmd` | _(none)_ | | `kilocode` | `agentsmd` | | `codex` | `agentsmd` | | `gemini` | _(none)_ | **Example:** Specifying `opencode` in config results in the transpilation order: `agentsmd` then `opencode`. ## Hidden Adapters Hidden adapters have `hidden: true` and: - Cannot be specified in `.agloom/config.yml`. - Cannot be used with `--adapter`. - Do not appear in `agloom adapters` output. - Are included only via `dependsOn` of another adapter, or when using `--all`. Currently, `agentsmd` is the only hidden adapter. --- # CLI Commands Source: https://docs.agloom.sh/reference/cli > Complete reference for all Agloom CLI commands, options, and exit codes # CLI Commands Agloom provides a command-line interface built on React + Ink for transpiling canonical configurations into agent-specific files. ## Global Options ### --help ```text agloom --help ``` Displays the general help message with a list of available commands and global options. Calling `agloom` without any command also displays this help. Exit code: `0`. ### --version ```text agloom --version ``` Displays the version of the installed Agloom package (read from `package.json`). Also available as `agloom version`. Exit code: `0`. ### Unknown Command If an unknown command is provided, Agloom displays: ```text Unknown command: . Run 'agloom --help' to see available commands. ``` Exit code: `1`. The `--help` flag does **not** suppress this error. Unknown command detection takes priority over global `--help`. ## Commands ### transpile Runs the transpilation pipeline for all registered transpiler modules. ```text agloom transpile [--adapter | --all] [--clean] [--verbose] [--refresh] ``` #### Options | Option | Type | Default | Description | | ----------------------- | ------- | ------- | -------------------------------------------------------------------------------- | | `--adapter ` | string | - | Adapter ID from the registry. Mutually exclusive with `--all`. | | `--all` | boolean | `false` | Transpile for all adapters in the registry. Mutually exclusive with `--adapter`. | | `--clean` | boolean | `false` | Run clean before transpiling (see [clean](#clean)). | | `--verbose` | boolean | `false` | Show all steps including those with 0 files. | | `--refresh` | boolean | `false` | Force re-fetch of cached git plugins. | When neither `--adapter` nor `--all` is specified, adapters are read from `.agloom/config.yml`. #### Adapter Resolution - `--adapter `: resolves the specified adapter and its dependencies (topological order). - `--all`: uses all adapters from the registry in definition order. - Neither: loads adapters from `config.yml`, resolves dependencies, deduplicates. Dependencies are resolved automatically. For example, `--adapter opencode` also transpiles the `agentsmd` adapter first (since `opencode.dependsOn = ["agentsmd"]`). #### Pipeline For each resolved adapter entry, the command executes transpiler steps in order: 1. Instructions 2. Skills 3. Agents 4. Docs 5. Schemas 6. Overlay step (MCP + Permissions) #### Verbose Filtering Without `--verbose`, steps with 0 written files and no errors are hidden. If all steps for all adapters are hidden and there are no errors, the output is: ```text Nothing to transpile. ``` #### --clean Behavior When `--clean` is provided, the clean procedure runs before transpilation for each adapter entry. With `--adapter`, the clean result is displayed before transpilation output. With `--all` or config mode, clean results are not displayed. #### Examples ```sh # Transpile using config agloom transpile # Transpile for a specific adapter agloom transpile --adapter claude # Transpile for all adapters with verbose output agloom transpile --all --verbose # Clean then transpile agloom transpile --clean ``` #### Exit Codes | Code | Condition | | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | All steps completed without errors. | | `1` | Any step had errors, both `--adapter` and `--all` specified, config not found (without `--adapter`/`--all`), config error, unknown/hidden adapter. | --- ### clean Removes generated agent-specific files. ```text agloom clean [--adapter | --all] [--verbose] ``` #### Options | Option | Type | Default | Description | | ----------------------- | ------- | ------- | -------------------------------------------------------------- | | `--adapter ` | string | - | Adapter ID from the registry. Mutually exclusive with `--all`. | | `--all` | boolean | `false` | Clean for all adapters. Mutually exclusive with `--adapter`. | | `--verbose` | boolean | `false` | Show details even when 0 files removed. | #### Behavior For each resolved adapter, the clean procedure: 1. Recursively removes directories listed in `entry.paths` (skills, agents, docs, schemas). 2. Deletes files listed in `entry.targetFiles`. Missing files and directories are silently skipped. #### Output Without `--verbose`, adapters with 0 removed files and no errors are hidden. If all adapters have 0 removed files: ```text Nothing to clean. ``` #### Examples ```sh agloom clean --adapter claude agloom clean --all agloom clean --verbose ``` #### Exit Codes | Code | Condition | | ---- | ------------------------------------------------------------------------------------------------------------------ | | `0` | All clean operations completed without errors. | | `1` | Both `--adapter` and `--all` specified, config not found, config error, unknown/hidden adapter, or deletion error. | --- ### init Imports existing agent-specific files into `.agloom/overlays/` and creates the configuration file. ```text agloom init [--adapter | --all] [--force] [--verbose] ``` #### Options | Option | Type | Default | Description | | ----------------------- | ------- | ------- | ----------------------------------------------------------------------- | | `--adapter ` | string | - | Adapter identifier. Mutually exclusive with `--all`. | | `--all` | boolean | `false` | Initialize all supported adapters. Mutually exclusive with `--adapter`. | | `--force` | boolean | `false` | Overwrite existing files. | | `--verbose` | boolean | `false` | Show all steps including 0-file ones. | #### Behavior 1. Resolves adapters (same rules as `transpile`). 2. Checks if `.agloom/` directory exists (error without `--force`). 3. Creates `.agloom/config.yml` when `--adapter` or `--all` is specified. 4. For each adapter, copies files from `entry.overlayImportPaths` into `.agloom/overlays//`. The generated `config.yml` includes onboarding comments: ```yaml # Agloom configuration # List of adapters to use by default when no --adapter or --all flag is provided. # Run 'agloom adapters --all' to see all available adapters. adapters: - claude ``` #### Examples ```sh agloom init --adapter claude agloom init --all agloom init --adapter opencode --force ``` #### Exit Codes | Code | Condition | | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `0` | All steps completed without errors (including 0 files). | | `1` | Both `--adapter` and `--all` specified, config not found (without flags), `.agloom/` already exists without `--force`, overlay directory exists without `--force`, copy or directory creation error. | --- ### adapters Lists available or active adapters. ```text agloom adapters [--all] ``` #### Options | Option | Type | Default | Description | | ------- | ------- | ------- | ---------------------------------------------------------------------------- | | `--all` | boolean | `false` | Show all available (non-hidden) adapters instead of active ones from config. | #### Behavior - Without `--all`: loads config and shows active adapters. If no config exists, falls back to showing all non-hidden adapters. - With `--all`: shows all non-hidden adapters from the registry. Hidden adapters (e.g., `agentsmd`) are never displayed. #### Output ```text Active adapters: claude Claude Code opencode OpenCode ``` Exit code: `0`. --- ### format Formats and lints project files (Markdown, JSON, YAML, TOML). ```text agloom format [--check] [--all] [...] ``` #### Options | Option | Type | Default | Description | | ----------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------------------------- | | `--check` | boolean | `false` | Check files without modifying. Exit code 1 if unformatted. | | `--all` | boolean | `false` | Format all supported files in the project (`**/*.{md,mdx,json,yaml,yml,toml}`). Mutually exclusive with `...`. | | `...` | string[] | - | Custom glob patterns or file paths. Mutually exclusive with `--all`. | #### Default Target Files When neither `--all` nor file arguments are provided: - `.agloom/**/*.{md,mdx,json,yaml,yml,toml}` - `**/AGLOOM.md` #### Supported Formats | Extension | prettier | markdownlint | | --------------- | -------- | ------------ | | `.md`, `.mdx` | Yes | Yes | | `.json` | Yes | No | | `.yaml`, `.yml` | Yes | No | | `.toml` | Yes | No | Unsupported extensions are silently skipped. #### Configuration Priority 1. Built-in defaults (bundled in `@agloom/markdown-tools`). 2. Native config files (`.prettierrc.*`, `.markdownlint.*` in project root). 3. `prettier` and `markdownlint` sections in `.agloom/config.yml` (shallow merge on top). #### Excluded Directories Glob expansion always excludes: `node_modules`, `.git`, `dist`, `build`, `coverage`, `.next`, `.turbo`, `.cache`, and paths matching `.gitignore`. #### Examples ```sh # Format default files agloom format # Check without modifying agloom format --check # Format all supported files agloom format --all # Format specific files agloom format "src/**/*.md" ".agloom/**/*.yaml" ``` #### Exit Codes | Code | Condition | | ---- | ----------------------------------------------------------------------------------------------------------- | | `0` | Format completed without errors, or all files pass check. | | `1` | Format errors, files need formatting (check mode), config parse error, or `--all` used with file arguments. | --- ### help Shows help topics or displays a specific help topic rendered from Markdown. ```text agloom help [] ``` #### Arguments | Argument | Type | Description | | --------- | ------ | -------------------------------------------------------------------------------------------------------------- | | `` | string | Topic name. Full format: `guide/getting-started`, `reference/cli`. Short format (slug only): `cli`, `plugins`. | #### Behavior Without ``: displays a categorized list of all available help topics (Guide and Reference). With ``: resolves the topic name, reads the corresponding Markdown file from `docs/guide/` or `docs/reference/`, strips frontmatter, and renders to the terminal using `marked` + `marked-terminal`. Short topic names (without category prefix) are searched across all categories. If the slug is ambiguous (exists in multiple categories), an error lists matching topics. #### Exit Codes | Code | Condition | | ---- | ------------------------------------------------------------------ | | `0` | Topic list displayed or topic rendered successfully. | | `1` | Topic not found, ambiguous topic, read error, no topics available. | --- ### cache clean Clears the plugin cache directory. ```text agloom cache clean ``` Git plugins are cached in `~/.agloom/cache/plugins/`. This command removes all cached plugins, forcing re-fetch on the next `transpile`. Exit code: `0`. --- # Configuration File Source: https://docs.agloom.sh/reference/config > Complete reference for .agloom/config.yml format, fields, and validation # Configuration File The file `.agloom/config.yml` is the project-level configuration for Agloom. It defines which adapters to use by default and optionally configures plugins, variables, and formatting tools. ## File Location ```text /.agloom/config.yml ``` The file is loaded by the commands `transpile`, `clean`, `init`, and `adapters` when neither `--adapter` nor `--all` is specified. ## Schema ### adapters - **Type:** `array` - **Required:** Yes - **Constraints:** Must not be empty. Each element must be a known, non-hidden adapter ID from the registry. List of adapter identifiers to use by default. ```yaml adapters: - claude - opencode ``` Hidden adapters (e.g., `agentsmd`) cannot be specified in `adapters`. They are included automatically when a dependent adapter (e.g., `opencode`) is resolved. ### plugins - **Type:** `array` - **Required:** No List of plugins to load. Each entry can be: **String form (git shorthand):** ```yaml plugins: - git@github.com:user/plugin - https://github.com/user/plugin ``` **Object form (local plugin):** ```yaml plugins: - path: ../my-local-plugin ``` **Object form (git plugin with options):** ```yaml plugins: - git: git@github.com:user/plugin ref: v1.0.0 path: packages/my-plugin values: team_name: platform api_token: "${env:API_TOKEN}" ``` | Field | Type | Description | | -------- | ------ | ---------------------------------------------------------------------------- | | `git` | string | Git URL (SSH or HTTPS). | | `path` | string | Local path (for local plugins) or subpath within git repo (for git plugins). | | `ref` | string | Git ref (tag, branch, commit SHA). Optional for git plugins. | | `values` | object | Key-value pairs passed to the plugin. All values must be strings. | ### variables - **Type:** `object` - **Required:** No Declares project-level variables accessible via `${values:NAME}` interpolation. **Shorthand form** (string value treated as default): ```yaml variables: project_name: "${env:PROJECT_NAME}" ``` **Full form:** ```yaml variables: team: description: "Team name" default: "platform" api_key: description: "API key" default: "${env:API_KEY}" sensitive: true required: true ``` Each variable declaration supports: | Field | Type | Default | Description | | ------------- | ------- | ------- | ----------------------------------------------------------------------------------- | | `description` | string | `""` | Description of the variable. Optional in config (required in plugin manifests). | | `required` | boolean | `false` | If `true`, variable must have a resolved value. | | `default` | string | - | Default value. May contain `${env:VAR}` for environment variable substitution. | | `sensitive` | boolean | `false` | If `true`, the value must reference an environment variable (cannot be set inline). | ### prettier - **Type:** `object` - **Required:** No Prettier configuration overrides. Values are passed to prettier as-is and shallow-merged on top of native config files and built-in defaults. ```yaml prettier: proseWrap: always tabWidth: 4 ``` ### markdownlint - **Type:** `object` - **Required:** No Markdownlint configuration overrides. Values are passed to markdownlint as-is. ```yaml markdownlint: MD013: line_length: 80 ``` ## Validation Rules The following conditions produce errors during config loading: | Condition | Error Message | | ------------------------------------------- | ----------------------------------------------------------------- | | `adapters` field missing | `Invalid config: 'adapters' field is required.` | | `adapters` is not an array of strings | `Invalid config: 'adapters' must be an array of strings.` | | `adapters` is empty | `Invalid config: 'adapters' must not be empty.` | | Unknown adapter ID | `Invalid config: unknown adapter ''.` | | Hidden adapter specified | `Invalid config: adapter '' cannot be specified in config.` | | `variables` is not an object | `Invalid config: 'variables' must be an object.` | | Variable value is neither string nor object | `Invalid config: variable '' must be a string or an object.` | | Plugin `values` is not an object | `Invalid config: plugin 'values' must be an object.` | | Plugin `values` entry is not a string | `Invalid config: plugin 'values' entry '' must be a string.` | ## Complete Example ```yaml # Agloom configuration adapters: - claude - opencode plugins: - git@github.com:cusxy/skill-cycling - git: git@github.com:cusxy/shared-agents ref: v2.0.0 values: team_name: "platform" api_token: "${env:CYCLING_API_TOKEN}" - path: ../local-plugin variables: project_name: "${env:PROJECT_NAME}" team: description: "Team name" default: "platform" api_key: description: "API key" default: "${env:API_KEY}" sensitive: true prettier: proseWrap: always markdownlint: MD013: line_length: 80 ``` --- # Interpolation Source: https://docs.agloom.sh/reference/interpolation > Complete reference for variable interpolation syntax, namespaces, and resolution # Interpolation Agloom supports variable interpolation in canonical files during transpilation. Variables are substituted with adapter-specific paths, environment values, or plugin/project values. ## Syntax ```text ${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: ```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. | Variable | Value | | -------------------- | --------------------------------- | | `PROJECT_DIR` | Absolute 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. | Variable | Source | | ------------- | ------------------------------ | | `SKILLS_DIR` | `currentAdapter.paths.skills` | | `AGENTS_DIR` | `currentAdapter.paths.agents` | | `DOCS_DIR` | `currentAdapter.paths.docs` | | `SCHEMAS_DIR` | `currentAdapter.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. | Pattern | Source | | ---------------------- | ----------------------- | | `{PREFIX}_SKILLS_DIR` | `adapter.paths.skills` | | `{PREFIX}_AGENTS_DIR` | `adapter.paths.agents` | | `{PREFIX}_DOCS_DIR` | `adapter.paths.docs` | | `{PREFIX}_SCHEMAS_DIR` | `adapter.paths.schemas` | Where `{PREFIX}` = `adapter.id.toUpperCase()`. **Example values:** | Variable | Value | | ---------------------- | ------------------- | | `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`. ```text ${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: ```text InterpolationError("Undefined environment variable: ") ``` ### values Plugin or project values resolved from `variables` declarations. See [config.md](config.md) for project variables and [plugin-manifest.md](plugin-manifest.md) for plugin variables. ```text ${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 ```text InterpolationError("Unknown values variable: ") ``` ## 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): ```text .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 | Condition | Error | | ------------------------ | -------------------------------------------------------------- | | Unknown `${agloom:NAME}` | `InterpolationError("Unknown agloom variable: ")` | | Undefined `${env:NAME}` | `InterpolationError("Undefined environment variable: ")` | | Unknown `${values:NAME}` | `InterpolationError("Unknown values variable: ")` | 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: ```markdown 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`): ```markdown Skills are at `.claude/skills`. Claude skills: `.claude/skills`. Project: myapp Team: platform Escaped: ${env:HOME} ``` After interpolation for the `opencode` adapter: ```markdown Skills are at `.opencode/skills`. Claude skills: `.claude/skills`. Project: myapp Team: platform Escaped: ${env:HOME} ``` --- # Patch Operations Source: https://docs.agloom.sh/reference/patch-operations > Reference for all patch operations used in .patch overlay files # Patch Operations Patch operations provide fine-grained control over structured files (JSON, JSONC, YAML, TOML) in overlays. Instead of replacing a file entirely (override) or deep-merging it (overlay), a `.patch` file applies targeted modifications using declarative markers. ## File Naming Convention Patch files use the naming pattern: ```text .patch. ``` The `.patch` suffix is removed when determining the target file. For example, `settings.patch.yaml` applies to `settings.yaml`. The format of the patch file may differ from the target. For example, `tsconfig.patch.yaml` can patch `tsconfig.json` — the patch is parsed as YAML, and the result is serialized as JSON. Suffixes `.patch` and `.override` are mutually exclusive. A file with both suffixes (e.g., `settings.patch.override.json`) is an error. ## Operations ### $set Replaces the value of a key entirely. Creates the key if it does not exist. **Value type:** any **Input:** ```json { "editor": { "fontSize": 14, "tabSize": 2 } } ``` **Patch:** ```yaml editor: fontSize: $set: 16 ``` **Result:** ```json { "editor": { "fontSize": 16, "tabSize": 2 } } ``` --- ### $merge Deep merges an object into the target. If the target does not exist, it is created as an empty object first. **Value type:** object **Input:** ```json { "editor": { "fontSize": 14, "tabSize": 2, "rulers": [80] } } ``` **Patch:** ```yaml editor: $merge: fontSize: 16 tabSize: 4 ``` **Result:** ```json { "editor": { "fontSize": 16, "tabSize": 4, "rulers": [80] } } ``` --- ### $mergeBy Merges an array of objects by a key field (similar to Kustomize strategic merge patch). **Value type:** object with fields: | Field | Type | Description | | ------- | -------------- | ---------------------------------------------------- | | `key` | string | Field name used for matching. | | `items` | array\ | Objects to merge. Each must contain the `key` field. | **Target:** must be an array of objects. **Behavior:** 1. For each item in `items`, find an element in the target array where the `key` field matches. 2. If found, deep merge the target element with the incoming item. 3. If not found, append the incoming item to the end. **Input:** ```json { "tasks": [ { "name": "build", "command": "tsc", "args": ["--strict"] }, { "name": "test", "command": "vitest" } ] } ``` **Patch:** ```yaml tasks: $mergeBy: key: name items: - name: build args: ["--strict", "--noEmit"] - name: lint command: eslint ``` **Result:** ```json { "tasks": [ { "name": "build", "command": "tsc", "args": ["--strict", "--noEmit"] }, { "name": "test", "command": "vitest" }, { "name": "lint", "command": "eslint" } ] } ``` --- ### $append Adds elements to the end of an array. **Value type:** array **Target:** must be an array. **Input:** ```json { "editor": { "rulers": [80, 120] } } ``` **Patch:** ```yaml editor: rulers: $append: [140] ``` **Result:** ```json { "editor": { "rulers": [80, 120, 140] } } ``` --- ### $prepend Adds elements to the beginning of an array. The order of elements in `$prepend` is preserved. **Value type:** array **Target:** must be an array. **Input:** ```json { "plugins": ["existing-plugin"] } ``` **Patch:** ```yaml plugins: $prepend: [first-plugin, second-plugin] ``` **Result:** ```json { "plugins": ["first-plugin", "second-plugin", "existing-plugin"] } ``` --- ### $remove Removes elements from an array by value. Uses strict equality (`===`) for scalars and deep equality for objects/arrays. Missing elements are silently skipped. **Value type:** array **Target:** must be an array. **Input:** ```json { "files": { "exclude": ["node_modules", "dist", ".cache"] } } ``` **Patch:** ```yaml files: exclude: $remove: [node_modules, .cache] ``` **Result:** ```json { "files": { "exclude": ["dist"] } } ``` --- ### $unset Removes keys from an object. Missing keys are silently skipped. **Value type:** array\ (list of key names to remove) **Target:** must be an object. **Input:** ```json { "editor": { "fontSize": 14, "wordWrap": "on", "minimap": true } } ``` **Patch:** ```yaml editor: $unset: [wordWrap, minimap] ``` **Result:** ```json { "editor": { "fontSize": 14 } } ``` --- ### $insertAt Inserts elements at a specific index in an array. **Value type:** object with fields: | Field | Type | Description | | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | | `index` | integer | 0-based insertion position. Negative values count from the end (`-1` = before last element). Clamped to `[0, length]`. | | `items` | array | Elements to insert. | **Target:** must be an array. **Input:** ```json { "plugins": ["a", "b", "c"] } ``` **Patch:** ```yaml plugins: $insertAt: index: 1 items: [x, y] ``` **Result:** ```json { "plugins": ["a", "x", "y", "b", "c"] } ``` ## Execution Order When multiple markers appear in the same node, they are applied in this fixed order: 1. `$unset` — remove keys first. 2. `$merge` — deep merge objects. 3. `$mergeBy` — merge array by key. 4. `$set` — set value (overwrites previous operations). 5. `$remove` — remove array elements. 6. `$insertAt` — insert at position. 7. `$prepend` — add to beginning. 8. `$append` — add to end. ### Combination Restrictions | Combination | Allowed? | | ------------------------------------ | --------------- | | `$set` + `$merge` | **No** — error. | | `$set` + `$mergeBy` | **No** — error. | | `$merge` + `$mergeBy` | Yes | | `$insertAt` + `$append` + `$prepend` | Yes | | `$append` + `$prepend` + `$remove` | Yes | ## Navigation Non-marker keys in a patch file navigate the object hierarchy. To set a value, use `$set`; plain non-object values without markers have no effect. ```yaml # This navigates to editor.fontSize, then sets it to 16 editor: fontSize: $set: 16 # This navigates but has no effect (no marker) editor: fontSize: 16 ``` ## Non-Existent Target Fields | Operation | Behavior when target field does not exist | | ----------- | ---------------------------------------------------- | | `$set` | Creates the key with the given value. | | `$merge` | Creates an empty object `{}`, then merges. | | `$mergeBy` | Creates an empty array `[]`, all items are appended. | | `$append` | Warning in errors, operation skipped. | | `$prepend` | Warning in errors, operation skipped. | | `$insertAt` | Warning in errors, operation skipped. | | `$remove` | Silent no-op. | | `$unset` | Silent no-op. | ## Error Handling Patch operations use a tolerant strategy: errors in individual files are collected in an `errors` array, and processing continues with remaining files. | Condition | Behavior | | ------------------------------------------------------- | ------------------------- | | Invalid patch file (parse error) | Error message, skip file. | | `$append`/`$prepend`/`$remove`/`$insertAt` on non-array | Error message, skip file. | | `$unset`/`$merge` on non-object | Error message, skip file. | | `$mergeBy` on non-array | Error message, skip file. | | `$mergeBy` item missing key field | Error message, skip file. | | `$mergeBy` item not an object | Error message, skip file. | | Invalid marker value type | Error message, skip file. | | Unknown marker (key starts with `$`) | Error message, skip file. | | Both `$set` and `$merge` in same node | Error message, skip file. | | Both `.patch` and `.override` suffixes | Error message, skip file. | --- # Plugin Manifest Source: https://docs.agloom.sh/reference/plugin-manifest > Complete reference for plugin.yml format, fields, and validation rules # Plugin Manifest The plugin manifest (`plugin.yml`) defines metadata for an Agloom plugin. It must be located at the root of the plugin directory. ## File Location ```text /plugin.yml ``` ## Plugin Directory Structure ```text / plugin.yml # Manifest (required) AGLOOM.md # Plugin instructions (optional) AGLOOM.local.md # Local plugin instructions (optional) overlays/ # Per-adapter overlay files (optional) claude/ opencode/ skills/ # Plugin skills (optional) agents/ # Plugin agents (optional) docs/ # Plugin docs (optional) schemas/ # Plugin schemas (optional) ``` The plugin directory mirrors the structure of `.agloom/` in a local project. A `config.yml` file must **not** be present in a plugin directory. ## Schema ### Required Fields #### name - **Type:** `string` - **Constraints:** Lowercase letters (`a-z`), digits (`0-9`), and hyphens (`-`). Must start with a letter, end with a letter or digit. No consecutive hyphens (`--`). Length: 1-214 characters. - **Regex:** `^[a-z]([a-z0-9]|(-(?!-)))*[a-z0-9]$|^[a-z]$` ```yaml name: my-eslint-config ``` Valid examples: `my-plugin`, `eslint-config`, `a`, `plugin1`. Invalid examples: `My-Plugin` (uppercase), `-plugin` (starts with hyphen), `plugin-` (ends with hyphen), `my--plugin` (consecutive hyphens), `my_plugin` (underscore). #### version - **Type:** `string` - **Constraints:** Must be a valid Semantic Versioning 2.0.0 string (validated via `semver.valid()`). ```yaml version: 1.0.0 ``` Valid examples: `1.0.0`, `0.1.0`, `1.2.3-beta.1`, `1.0.0+build.123`. Invalid examples: `1.0` (incomplete), `v1.0.0` (`v` prefix), `1.0.0.0` (extra component). #### description - **Type:** `string` - **Constraints:** Must be a non-empty string. ```yaml description: "Shared ESLint configuration for agloom projects" ``` #### author - **Type:** `object` | Field | Type | Required | Constraints | | ------- | ------ | -------- | --------------------------------------------------------- | | `name` | string | Yes | Non-empty string. | | `email` | string | Yes | Non-empty string. | | `url` | string | No | Must be a valid URL (parseable by the `URL` constructor). | ```yaml author: name: "John Doe" email: "john@example.com" url: "https://example.com" ``` ### Optional Fields #### license - **Type:** `string` - **Constraints:** Non-empty string. Should be an SPDX identifier (e.g., `MIT`, `Apache-2.0`). ```yaml license: MIT ``` #### homepage - **Type:** `string` - **Constraints:** Must be a valid URL. ```yaml homepage: "https://github.com/example/my-eslint-config" ``` #### keywords - **Type:** `array` - **Default:** `[]` - **Constraints:** Each element must be a non-empty string. ```yaml keywords: - eslint - config ``` #### variables - **Type:** `object` - **Default:** `null` (plugin does not accept variables) Declares variables that consumers can set via `values` in their `config.yml`. Each key is a variable name; each value is a `VariableDeclaration` object. | Field | Type | Default | Description | | ------------- | ------- | ------------ | ----------------------------------------------------------------- | | `description` | string | **required** | Description of the variable. | | `required` | boolean | `false` | If `true`, the variable must be provided or have a default. | | `default` | string | - | Default value. May contain `${env:VAR}`. | | `sensitive` | boolean | `false` | If `true`, value must reference `${env:VAR}` (no inline secrets). | ```yaml variables: team_name: description: "Team name for commit messages" required: true api_token: description: "API token for external service" required: true sensitive: true lint_command: description: "Custom lint command" default: "pnpm run lint" base_url: description: "Base URL for API calls" default: "${env:BASE_URL}" ``` ## Validation Rules | Condition | Error Message | | ------------------------------------ | --------------------------------------------------------------------------------------------- | | `plugin.yml` not found | `Plugin manifest not found: /plugin.yml` | | Invalid YAML | `Invalid plugin manifest: ` | | `name` missing | `Invalid plugin manifest: 'name' is required.` | | `name` invalid format | `Invalid plugin manifest: 'name' must contain only lowercase letters, digits, and hyphens...` | | `version` missing | `Invalid plugin manifest: 'version' is required.` | | `version` invalid semver | `Invalid plugin manifest: 'version' must be a valid semver string.` | | `description` missing | `Invalid plugin manifest: 'description' is required.` | | `description` not a non-empty string | `Invalid plugin manifest: 'description' must be a non-empty string.` | | `author` missing | `Invalid plugin manifest: 'author' is required.` | | `author` not an object | `Invalid plugin manifest: 'author' must be an object.` | | `author.name` missing or empty | `Invalid plugin manifest: 'author.name' must be a non-empty string.` | | `author.email` missing or empty | `Invalid plugin manifest: 'author.email' must be a non-empty string.` | | `author.url` invalid URL | `Invalid plugin manifest: 'author.url' must be a valid URL.` | | `license` not a non-empty string | `Invalid plugin manifest: 'license' must be a non-empty string.` | | `homepage` invalid URL | `Invalid plugin manifest: 'homepage' must be a valid URL.` | | `keywords` not an array | `Invalid plugin manifest: 'keywords' must be an array of strings.` | | Keyword not a non-empty string | `Invalid plugin manifest: each keyword must be a non-empty string.` | | `variables` not an object | `Invalid plugin manifest: 'variables' must be an object.` | | Variable not an object | `Invalid plugin manifest: variable '' must be an object.` | | Variable `description` missing/empty | `Invalid plugin manifest: variable '' must have a non-empty 'description'.` | ## Complete Example ```yaml name: my-eslint-config version: 1.0.0 description: "Shared ESLint configuration for agloom projects" license: MIT author: name: "John Doe" email: "john@example.com" url: "https://example.com" homepage: "https://github.com/example/my-eslint-config" keywords: - eslint - config variables: team_name: description: "Team name" required: true api_token: description: "API token" required: true sensitive: true lint_command: description: "Custom lint command" default: "pnpm run lint" ``` --- # Transpilers Source: https://docs.agloom.sh/reference/transpilers > Reference for all transpiler modules, pipeline order, and overlay step # 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: ```markdown This content only appears in CLAUDE.md output. This content only appears in AGENTS.md output. ``` 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 `` tags: | Agent ID | Valid? | Reason | | ---------- | ------ | ------------------------------- | | `claude` | Yes | Has `CLAUDE.md` | | `agentsmd` | Yes | Has `AGENTS.md` | | `gemini` | Yes | Has `GEMINI.md` | | `opencode` | No | Uses `AGENTS.md` via `agentsmd` | | `kilocode` | No | Uses `AGENTS.md` via `agentsmd` | | `codex` | No | Uses `AGENTS.md` via `agentsmd` | ### Frontmatter Override The canonical frontmatter may contain an `override` block with per-agent key overrides (shallow merge): ```yaml --- 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 | Adapter | Input | Output | | ---------- | ----------- | ------------------------------------ | | `claude` | `AGLOOM.md` | `CLAUDE.md` (same relative location) | | `agentsmd` | `AGLOOM.md` | `AGENTS.md` (same relative location) | | `gemini` | `AGLOOM.md` | `GEMINI.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: ```yaml --- 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: | Mode | Behavior | Adapters | | ------------ | -------------------------------------------------------- | ------------------------------- | | **Preserve** | Subdirectory structure is maintained in the output | `claude`, `gemini` | | **Flatten** | All files are placed in the root of the target directory | `opencode`, `kilocode`, `codex` | When flattening, if files from different subdirectories have the same filename, transpilation fails with a name conflict error. ### Output Per Adapter | Adapter | Output Directory | Format | Subdirs | | ---------- | -------------------------------- | --------------------------- | --------------------- | | `claude` | `.claude/commands/` | Markdown | Preserve | | `opencode` | `.opencode/commands/` | Markdown | Flatten | | `kilocode` | `.kilo/commands/` | Markdown | Flatten | | `gemini` | `.gemini/commands/` | TOML (`.toml` extension) | Preserve | | `codex` | `.agents/skills//SKILL.md` | Markdown (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//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//` 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//` 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: | Adapter | Output Directory | | ---------- | --------------------------- | | `claude` | `.claude/skills//` | | `opencode` | `.opencode/skills//` | | `kilocode` | `.kilo/skills//` | | `codex` | `.agents/skills//` | | `gemini` | `.gemini/skills//` | | `agentsmd` | _(no output — empty paths)_ | --- ## Agents Transpiler **Source:** `.agloom/agents/.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: ```yaml --- 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: | Adapter | Output Directory | | ---------- | ---------------------------- | | `claude` | `.claude/agents/.md` | | `opencode` | `.opencode/agents/.md` | | `kilocode` | `.kilo/agents/.md` | | `codex` | `.codex/agents/.md` | | `gemini` | `.gemini/agents/.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 | Adapter | Output Directory | | ---------- | ----------------- | | `claude` | `.claude/docs/` | | `opencode` | `.opencode/docs/` | | `kilocode` | `.kilo/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 | Adapter | Output Directory | | ---------- | -------------------- | | `claude` | `.claude/schemas/` | | `opencode` | `.opencode/schemas/` | | `kilocode` | `.kilo/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. ### Canonical Format ```yaml 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 ``` Each server entry supports: | Field | Type | Description | | -------------- | -------------- | ------------------------------------------------------------ | | `command` | string | Command to start the MCP server. | | `args` | array\ | Command arguments. | | `env` | object | Environment variables for the server process. | | `includeTools` | array\ | Whitelist of tools (mutually exclusive with `excludeTools`). | | `excludeTools` | array\ | Blacklist of tools (mutually exclusive with `includeTools`). | ### Output Per Adapter | Adapter | Output File | Format | | ---------- | --------------- | ------------------------------------------------------------------------------------- | | `claude` | `.mcp.json` | `{ mcpServers: { ... } }` with tool filtering via `autoApprove`/`disabled` fields. | | `opencode` | `opencode.json` | MCP servers in the `mcp` section. Tool filtering fields are stripped (not supported). | 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. ```yaml shell: - "git status *": allow - "git push *": ask - "*": deny mcp: - "bitbucket:*": allow - "*:*": ask file: - "src/**": write - "**": read ``` | Section | Pattern Format | Actions | | ------- | ---------------------------------------- | ----------------------- | | `shell` | Glob matched against full command string | `allow`, `ask`, `deny` | | `mcp` | `:` format | `allow`, `ask`, `deny` | | `file` | Glob matched against file path | `deny`, `read`, `write` | All sections are optional. ### Output Per Adapter | Adapter | Output | Notes | | ---------- | --------------------------------------------- | -------------------------------------------------------- | | `claude` | `.claude/settings.json` (permissions section) | First-match-wins semantics preserved. | | `opencode` | `opencode.json` (permission section) | Rule order **inverted** (OpenCode uses last-match-wins). | 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//` to the project root. ### File Merge Strategies The strategy for each file is determined by its extension and naming: | Condition | Strategy | | ---------------------------------------------------------------------- | ----------------------------------- | | Has `.override` suffix (e.g., `settings.override.json`) | **Override** — full replacement. | | Has `.patch` suffix + merge-eligible extension | **Patch** — declarative operations. | | Merge-eligible extension (`.json`, `.jsonc`, `.yaml`, `.yml`, `.toml`) | **Overlay** — deep merge. | | All other extensions | **Override** — full replacement. | ### 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//`) 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.