> For the complete documentation index, see [llms.txt](https://tinyhumans.gitbook.io/medulla/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tinyhumans.gitbook.io/medulla/features/workspace-profiles.md).

# MEDULLA.md

An orchestrator's roster tells it who it can delegate to. It says nothing about what a directory actually is. Handed five repositories and a fleet of harnesses, a model with no other information will guess, and it will guess plausibly and wrongly.

`AGENTS.md` and `CLAUDE.md` do not solve this. They are written for a coding agent working inside a repository, so they are long, prose-heavy, and carry no routing preferences at all. An orchestrator reads its context on every cycle, which makes a thousand-line house-style document the wrong shape.

`MEDULLA.md` is the right shape: one short file at a workspace root, roughly 100 to 200 tokens, describing what the repository is and how work over it should be routed.

## What one looks like

YAML frontmatter carries the machine-readable preferences and the Markdown body carries the summary.

```markdown
---
harnesses: [claude-code, opencode]
models:
  reasoning: [claude-opus-4-8]
  compress: [claude-haiku-4-5]
routing: |
  Billing changes -> the payments agent.
  Schema migrations -> review before delegating.
  Never delegate work that touches credentials.
---

Payments service. Owns billing, invoices, and the Stripe integration.
Decompose billing changes per bounded context and keep migrations in their
own task.
```

Every key is optional, and the body is the load-bearing part. A profile that is nothing but prose is completely valid. The frontmatter is a bonus.

| Key         | What it expresses                                                                                                                         |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `harnesses` | Harnesses to prefer for work in this workspace.                                                                                           |
| `models`    | Preferred models, optionally scoped per tier (`reasoning`, `compress`, `orchestrator`). A flat list reads as a reasoning-tier preference. |
| `routing`   | Freeform guidance, for the rules that do not fit a schema.                                                                                |

Write the body as instructions for an orchestrator rather than marketing copy: what the code does, the important entry points, and the house rules that should shape how work gets decomposed. The first line becomes the repository's one-sentence identity in the roster, so lead with it.

## Advisory, never enforced

This is the design decision with the most consequences. Medulla renders your preferences into the orchestrator's context as guidance the model reasons over. It does not filter delegation targets, reject models, or fail a cycle over a violation.

Routing is a cognitive decision. A hard constraint, such as forbidding a model outright or putting a directory off limits, is policy, and policy belongs to the host system that can actually enforce it rather than to a document the model reads.

The same instinct runs through the format. Parsing never throws, so malformed frontmatter degrades to a summary-only profile instead of failing. A profile is operator-authored, and an authored file should never be able to break a running operation.

## One per root, no cascade

`CLAUDE.md` and `AGENTS.md` cascade, so a file in a subdirectory layers over one above it. `MEDULLA.md` deliberately does not. There is no global-versus-project precedence and no merge semantics. Every profile in play is presented together, each tagged with the workspace it describes.

For an umbrella repository with several component repositories underneath, that means each component root carries its own profile, and the orchestrator sees all of them side by side instead of a resolved winner.

## What it changes

A profile shapes two things. It shapes the orchestrator's and reasoning tier's context, which is where the routing preferences and the summary land, appended below whatever prompt is already in play rather than replacing it. It also shapes the roster, where an agent rooted in a profiled workspace gains a one-line identity drawn from the summary.

Workers themselves never read `MEDULLA.md`. It shapes how work is decomposed and who it goes to, upstream of any worker starting. With no profiles anywhere, behaviour is identical to a build that never had the feature.

## Writing one

```sh
medulla workspace add            # profile + register the current directory
medulla workspace add ./payments # or a specific one
```

`workspace add` reads whatever the directory already has, meaning `AGENTS.md`, `CLAUDE.md`, and `README.md`, then asks a model to distil it into a summary plus routing hints. It also scans the directory's file layout, so the orchestrator knows which paths the workspace is made of and not just what it is. Treat the draft as a starting point rather than the final word: the summary is what the orchestrator actually reads on every cycle, so it is worth a pass by hand.

Writing the file is only half of it. `workspace add` also **registers** the directory in your config, which is what makes the orchestrator aware of it at all — an unregistered profile is never read. Re-running the command is safe: an already-registered directory is refreshed, not duplicated, and a `MEDULLA.md` that already exists is kept rather than overwritten.

```sh
medulla workspace list        # what the orchestrator knows about
medulla workspace remove .    # stop placing work here (files untouched)
```

`medulla init` writes the `MEDULLA.md` alone, without registering — useful for drafting a profile in a directory that should not yet take work.

The `--force` flag redrafts an existing profile. Without it, authored work is never discarded: `workspace add` keeps the file and registers anyway, and `init` refuses rather than overwriting. The `--offline` flag skips the model and writes an editable stub. If no model is available, or the call fails, both degrade to the stub and say so, so you are always left a usable file.

See [CLI Reference](/medulla/developers/cli-reference.md) for the full flag list and [Orchestrator Routing](/medulla/features/routing.md) for how these preferences meet Medulla's own routing decisions.
