Skip to content

Contributing to Foundry

For engineers extending Foundry itself — this page is the skill-authoring standard. Everything Foundry ships is a skill, so contributing means writing one (or improving one) to the conventions below. If you're a Foundry user (consuming it via npx @engineering11/e11-foundry install), this page isn't for you; see Installation and the rest of the guide.

Repo layout

text
e11-foundry/                    # pnpm monorepo root (private)
├── packages/
│   ├── foundry/                # @engineering11/e11-foundry — published to GitHub Packages
│   │   ├── src/
│   │   │   ├── foundry/        # The Foundry module
│   │   │   │   ├── tasks/      # Anytime tools — one skill directory each
│   │   │   │   ├── workflows/  # Lifecycle skills, grouped by phase folder
│   │   │   │   ├── teams/      # Roster data
│   │   │   │   ├── data/       # Shared templates
│   │   │   │   ├── module.yaml # Install prompts + agent roster
│   │   │   │   └── module-help.csv   # The command catalog
│   │   │   └── scripts/        # resolve-customization.mjs, resolve-config.mjs, …
│   │   ├── tools/              # CLI, installers, validators
│   │   ├── templates/          # Starter templates (skill-template/)
│   │   └── test/skills/        # Vitest suites for skill helper scripts
│   ├── guide/                  # @engineering11/foundry-guide — this site
│   └── eval/                   # Behavioral eval harness
└── pnpm-workspace.yaml

Development setup

bash
git clone https://github.com/engineering11/e11-foundry
cd e11-foundry
pnpm install
pnpm run build              # TypeScript compile + asset copy

pnpm run build:check runs tsc --noEmit for fast type checks.

What a skill is

A skill is a directory containing, at minimum:

  • SKILL.md — the instructions. Frontmatter requirements:
    • name must match the directory name exactly.
    • description is one sentence saying what the skill does, followed by the trigger phrases that should activate it ("Use when the user says …"). The description is how host tools route requests — write it for the router, not for humans browsing.
  • customize.toml — the skill's customization surface: a [workflow] table as the baseline, or an [agent] table for agent personas. Every customizable behavior the skill has is declared here as data (see below).

Plus, as needed: a steps/ directory, templates, checklists, and references/ files the body loads just-in-time, and scripts/ for .mjs helpers.

Every skill body carries the shared conversation rules, in its RULES block (step files) or activation (agents): speak in {communication_language}, and never emit a bare code or IDAC4, [DF], CAP-2, FR3, story keys are always paired with a human-readable name on first use in a message. Copy both lines verbatim from a shipped skill rather than retyping them; readers shouldn't need a decoder ring, and the wording should not drift per skill.

Where skills live

  • tasks/<skill-name>/ — anytime tools: skills with no lifecycle position, invokable at any point (help, knowledge, refine, the review finders, shard/index, customize).
  • workflows/<N-phase>/<skill-name>/ — lifecycle skills: anything that belongs to a delivery phase (1-analysis5-scaffold), including the phase's agent-skill.

That's the whole rule. If a skill has a phase, it lives in the phase folder; if it doesn't, it's a task.

Pick a body shape

Three canonical shapes. Match the skill you're writing to one of them — don't invent a fourth.

1. Prose sections — short single-purpose tools

For a tool that does one thing in one pass (canonical example: e11-index-docs). The body is plain Markdown sections:

  • Goal / Your Role — one line each.
  • Inputs — named inputs with one-line descriptions.
  • EXECUTION — numbered steps as prose. Small enough to be read whole.
  • OUTPUT FORMAT — the exact shape of what the skill returns or writes.
  • HALT CONDITIONS — when to stop and what to say.

No activation ceremony unless the skill needs config or customization at run time; retrievers that other skills call constantly (like e11-knowledge) keep activation deliberately cheap.

2. steps/ directory — multi-stage interactive workflows

For anything with checkpoints, user decisions, or distinct stages (canonical example: e11-code-review). The SKILL.md holds the standard On Activation block (resolve the [workflow] block through the customization layers → prepend steps → persistent facts → config → greet → append steps — copy it from an existing skill, don't retype it) plus the step-processing rules; the procedure itself lives in steps/step-NN-<name>.md files:

  • Numbered step-01-…, step-02-…; the agent loads exactly one step at a time, just-in-time, never pre-loading the rest.
  • Each step is self-contained: rules, instructions, checkpoints, and an explicit NEXT ("read fully and follow ./step-02-….md") or a HALT.
  • Runtime state ({diff_output}, {spec_file}, …) is declared in step frontmatter and threaded between steps.

3. Agents — the shared activation protocol

Agents are skills whose entire body is the eight-step activation protocol: resolve the [agent] block, prepend steps, adopt persona, persistent facts, config, greet, append steps, dispatch-or-present-the-menu. Copy the body from an existing e11-agent-* skill and change only the Overview (the hardcoded identity) — the protocol text is shared and should not drift per agent. Everything an agent does — persona fields, principles, facts, menu — is data in its customize.toml, not prose in the body. Register the agent in module.yaml's agents: roster so it lands in central config.

Older skills: some bodies still use an XML-ish inline dialect (<workflow><step n="1">…). It's supported and won't be rewritten wholesale, but do not use it for new skills — pick one of the three shapes above.

customize.toml conventions

The surface is a contract with every team that installs Foundry, so it's held to rules:

  1. DO-NOT-EDIT header. Every file starts with the comment block naming the override files (.foundry/custom/<skill>.toml / .user.toml) and the merge rules (scalars override · arrays append · keyed arrays replace-or-append). Copy it from any shipped skill.
  2. Baseline fields. Every surface ships activation_steps_prepend, activation_steps_append, persistent_facts, and on_complete (workflow surfaces), or their [agent] equivalents plus persona fields and [[agent.menu]].
  3. Content-anchored knobs only. Every field must be read somewhere in the skill body. A knob the body never consults is a lie to the customizer — don't ship speculative fields.
  4. Keyed arrays use id or code. Any array-of-tables a user might want to override entry-by-entry ([[workflow.review_layers]], [[agent.menu]], [[workflow.extra_query_keys]]) carries a stable id/code key so overrides can replace one entry surgically.
  5. Platform-behavior gates use the e11_platform_* prefix. Any boolean that turns E11-specific behavior on or off (alloy pre-loads, capability maps, SDK stamps) is named e11_platform_<behavior>, defaults to true, and the body checks it before running the gated step — that's what lets a non-platform repo turn the behavior off with a one-line override.
  6. No removal semantics. Overrides can't delete — design fields so an empty value neutralizes (empty instruction disables a review layer, false disables a gate).

E11 grafts

When platform behavior must live inside a skill body that otherwise tracks a generic shape, mark it:

markdown
<!-- E11-GRAFT:begin <graft-name> -->

…the platform-specific steps…

<!-- E11-GRAFT:end <graft-name> -->

(# E11-GRAFT (<graft-name>): as a leading comment in TOML.) The markers make platform grafts findable and diffable as a unit.

Prefer the customize surface over inline grafts. If the behavior can be expressed as data — a gated field, an extra review layer, a persistent fact — put it in customize.toml where teams can override it, and keep the body graft to the minimal hook that reads it. Every inline graft should be gated by an e11_platform_* field.

Catalog registration

  • Menu codes are unique across the whole catalog (module-help.csv), not per agent. Check before claiming one.
  • Every user-facing skill gets a row in module-help.csv — columns: module · phase · name · code · sequence · workflow-file (skill:<name>) · command · required · agent · options · description · output-location · outputs. Tasks use phase=anytime. The installer assembles all module catalogs into .foundry/_config/e11-help.csv, which is what E11 Master and e11-help read — a skill missing its row is invisible to routing.
  • Skills reached only through an agent's menu also get their [[agent.menu]] entry in that agent's customize.toml.

Starter template

Start new skills from packages/foundry/templates/skill-template/ — it carries the frontmatter shape, the DO-NOT-EDIT header, the baseline surface fields, and the activation preamble in each variant. (If the template isn't in your checkout yet, copy the nearest shipped skill of the same body shape instead — that's what the template is distilled from.)

Testing and gates

  • Helper scripts get tests. Any scripts/*.mjs a skill ships gets a vitest suite under packages/foundry/test/skills/<skill-name>/ (see test/skills/e11-discovery/ for the pattern). Run with pnpm --filter @engineering11/e11-foundry test.

  • Repo gates — run before opening a PR:

    bash
    pnpm --filter @engineering11/e11-foundry test   # vitest suites
    pnpm run validate:refs                          # every file reference inside skills resolves
    pnpm run validate:guide                         # guide coverage of the catalog
    pnpm run lint && pnpm run format:check          # ESLint / Prettier, 0-warning baseline
    pnpm run lint:md                                # markdownlint over *.md
    pnpm run lint:vocabulary                        # banned-vocabulary lint

    Pre-commit hooks (Husky + lint-staged) run lint/format/markdownlint on staged files automatically.

Guide coverage

pnpm run validate:guide fails the moment a lifecycle skill exists without a guide reference: every workflows/<phase>/<slug>/SKILL.md must be linked from its phase page (packages/guide/02-workflows/<phase>.md). When you add a skill, add it to the phase page's table (or, for agents, a depth page under packages/guide/01-agents/ plus a row in the quick-reference table).

Guide depth pages follow an 8-section shape: What it produces · When to use it · How to invoke · Inputs · Outputs & where they land · Example session · Gotchas · Source.

Doc site

The guide deploys to foundry.engineering11.com via .github/workflows/docs.yml on pushes to main that touch packages/guide/.

bash
pnpm run docs:dev              # local server with hot reload
pnpm run docs:build            # build static site

Sidebar/nav live in packages/guide/.vitepress/config.mts — add new pages to the relevant sidebar group. Cross-repo links (../../src/...) are for GitHub readers and skipped by the dead-link checker; intra-guide links are checked and fail the build when broken.

Releases

Releases go through changesets: pnpm changeset in your PR describes the change and bump level; the release workflow versions and publishes @engineering11/e11-foundry to GitHub Packages.

What not to commit

.gitignore already covers it, but as a reminder:

  • .foundry/, .foundry-output/ — consumer install output, never inside Foundry itself.
  • .claude/, .agents/, .opencode/ — tool surfaces are generated, not authored.
  • Generated dist/.

Source

Skill sources: packages/foundry/src/foundry/tasks/ · packages/foundry/src/foundry/workflows/ · catalog: packages/foundry/src/foundry/module-help.csv · resolvers: packages/foundry/src/scripts/ · CLI + validators: packages/foundry/tools/ · tests: packages/foundry/test/skills/ (repo paths — open them in your checkout)

Proprietary to Engineering11 LLC.