> ## Documentation Index
> Fetch the complete documentation index at: https://docs.seriora.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# How extensions load

> One discovery model behind agents, skills, rules, MCP servers and hooks.

Five kinds of extension exist, and they share one loading model. Learning it once tells you where
to put any of them.

| Kind                       | What it is                                 | Runs in                         |
| -------------------------- | ------------------------------------------ | ------------------------------- |
| [Agent](/guides/subagents) | a role with its own context and tool grant | a child model run               |
| [Skill](/guides/skills)    | a procedure                                | the session's own context       |
| [Rule](/guides/rules)      | a standing instruction                     | the prompt, or the conversation |
| [MCP server](/guides/mcp)  | remote tools                               | the model's tool set            |
| [Hook](/guides/hooks)      | a script at a fixed point in the loop      | outside the model entirely      |

## Two scopes

Every kind is looked for in the same two places, in this order.

1. **Your profile root**, `~/.seri/<kind>/`, which applies to every project.
2. **The project**, `.seri/<kind>/`, found by walking up from where you started seri to the first
   ancestor that has one.

The project wins when both define the same name.

That upward walk refuses one candidate on purpose. It will not adopt `~/.seri/<kind>` as a
project scope, because a repository that happens to sit under your home directory would otherwise
claim your default profile's extensions as its own, and a `--profile work` run would reach them
through that back door. The comparison is case-folded on Windows and macOS, where one directory
routinely has two spellings.

## A bad file is skipped, not fatal

Across all five kinds, a file that does not parse, or that takes a name already claimed, is
skipped with a warning at startup naming the file. The session still starts.

That is the same judgement in every loader. A typo in one agent file should not cost you the
session, and a silent skip should not cost you the afternoon.

## What each one costs at session start

| Kind              | Loaded eagerly                   | Loaded when it fires             |
| ----------------- | -------------------------------- | -------------------------------- |
| Agent             | name, description                | the system prompt for that child |
| Skill             | name, description, argument hint | the procedure body               |
| Rule, always-on   | the whole text                   |                                  |
| Rule, glob-scoped | nothing                          | the whole text, once per session |
| MCP server        | the cached tool catalog          |                                  |
| Hook              | the manifest                     | the script                       |

A directory of twenty skills costs twenty descriptions, not twenty procedures.

## Compatibility, but not auto-adoption

The file formats are Cursor's and Claude Code's, unchanged, so existing agent files, `SKILL.md`
files, `.mdc` rules and hook scripts work when you copy them in.

seri does not read `.cursor/agents/`, `.claude/agents/`, `.cursor/skills/` or `.cursor/hooks/`
itself. An artifact written for another harness's toolset and another load contract loading
automatically here is a surprise rather than a convenience. Compatibility lives in the format,
and migrating is copying the files in.

## Hooks are the one exception to loading on sight

Rules and skills carry text. A hook carries a program, and it runs in front of the permission
gate on tools that never prompt, so an untrusted one would be code execution from a `git clone`
with nothing asked of you first.

Hooks in your profile root run, because nothing arrives there by cloning anything. A project's
hooks are found, listed and left dormant until you read them and run `/hooks trust`, and the
trust is bound to the bytes rather than the path.
