What Morphic Is
A vocabulary for describing the agents that do the work, and the software they are working on.
Here is a problem I actually had.
I had a directory of Markdown files describing AI agents and skills. Each one had YAML frontmatter and a body of instructions. Two of them needed the same three paragraphs about how to read the project's specification. So I copied the paragraphs. Then there were five. Then I changed one of them and forgot the other four, and an agent spent an afternoon confidently doing the wrong thing based on instructions I had personally fixed a week earlier.
Markdown files have no inheritance. Psy does.
use "@psy/morphic"
export skill ProjectContext:
description: Read the project before changing it.
when: Use before making any edit.
prompt:
Read the project's README, its configuration, and the code nearest to
the change before making any edit.
export skill ImplementChange extends ProjectContext:
description: Implement a change end to end.
when: Use whenever a change alters behaviour.
prompt:
+ super
Add or update tests for every behavioural change.psy build.claude/skills/implement-change/SKILL.md:
---
name: implement-change
description: Implement a change end to end. Use whenever a change alters behaviour.
---
# ImplementChange
Read the project's README, its configuration, and the code nearest to the change
before making any edit.
Add or update tests for every behavioural change.Two real Markdown files, with the shared paragraph appearing in both, from one source. Change it once and both regenerate.
That is the first half of Morphic. There is a second half, and it turned out to matter more.
The second problem
Deduplicating instructions makes your agents consistent. It does not make them correct.
An agent that has been told exactly how you like your tests written, and nothing about what you are building, will write beautifully-tested code for the wrong program. It will invent an architecture. It will name things plausibly and wrongly. It will "fix" a deliberate design decision because nothing told it the decision was deliberate. Then you review it, explain the architecture in the review, and the next task starts from zero again.
The missing input is not better instructions. It is a description of the software — one that lives in the repository, is checked by a compiler, and gets handed to the agent automatically when it is relevant.
export component LayerStack:
description: The ordered stack of layers in a document.
responsibilities:
- Maintain layer order and z-index
- Apply blend modes and opacity
invariants:
- Order is stable across save and load
- The renderer never mutates it---
name: layer-stack
description: "Component: The ordered stack of layers in a document."
---
# LayerStack
## Responsibilities
- Maintain layer order and z-index
- Apply blend modes and opacity
## Invariants
- Order is stable across save and load
- The renderer never mutates it
## Authority
This describes the product as it is meant to work. Where the implementation
disagrees, treat this as correct unless the task is explicitly to change it.That is the second half, and it is what Specifying Software is about.
Two families, one vocabulary
Morphic adds eight declaration keywords in two families, and nothing else.
How to work. Imperative. Generated as instructions.
| Keyword | Is |
|---|---|
skill | a reusable instruction other declarations build on |
agent | an autonomous worker with a toolset and a model |
command | something a person invokes by name |
What is being built. Declarative. Generated as reference material.
| Keyword | Describes |
|---|---|
concept | an idea you have to understand, starting with the program itself |
domain | a logical area, and what belongs to it |
feature | a specific behaviour |
component | a reusable unit of implementation |
reference | cross-cutting material: voice, naming, visual language |
They are separate because they change for different reasons. Skills change when your process changes. Definitions change when the product changes. Keep them in one bucket and every product change churns your instructions, and every process change churns your architecture docs.
And they are linked in exactly one direction: a skill, agent or command names the
definitions it needs with context.
export skill ImplementRendering:
description: Implement a change in the renderer.
when: Use when changing anything under the rendering domain.
context:
- Rendering
- LayerStack
prompt:
Keep mutation out of the renderer.---
name: implement-rendering
description: Implement a change in the renderer. Use when changing anything under the rendering domain.
---
# ImplementRendering
Keep mutation out of the renderer.
## Context
Consult these definitions of how the product works:
- `rendering` (Rendering)
- `layer-stack` (LayerStack)An agent that picks up that skill is handed the canvas rules. It does not go looking, and it does not guess.
Psy knows nothing about any of this
Worth being clear, because it is the reason the design holds together.
Morphic is an ordinary Psy framework, built exactly the way
Your Own Keywords described. The keywords exist only because
@psy/morphic exports abstract specs that expose them with as, and only in
modules that use it. The core compiler has never heard of a skill or an agent,
and could not be made to care about one.
All eight are ordinary specs. They inherit. They compose prompts with + super.
They carry any extra properties you invent.
Turning it on
// src/skills/ReviewDiff.psy
use "@psy/morphic"
export skill ReviewDiff:
description: Review a diff for correctness and clarity.
when: Use before approving any change.
prompt:
Read the whole diff before commenting on any part of it.// psy.config.ts
import { defineConfig } from "@psy/config";
import { morphic } from "@psy/morphic";
import { claude } from "@psy/adapter-claude";
export default defineConfig({
source: ["./src"],
frameworks: [morphic()],
targets: [claude({ output: ".claude" })],
});Morphic ships as one package with two halves that travel together:
| Half | What it is | What it does |
|---|---|---|
| Psy | psy/framework.psy | declares the keywords and what each accepts |
| TypeScript | morphic() | enforces the rules a type cannot express |
You want both. The Psy half so the keywords exist; the TypeScript half so
psy check catches an empty prompt.
use "@psy/morphic" resolves the package's Psy entry point. A standalone psy
binary carries its own copy, so this works in a project that has installed nothing
at all.
Taking only half
use "@psy/morphic" activates all eight keywords. To take only the working half:
use "@psy/morphic/psy/framework"Rarely worth it — unused keywords cost nothing — but it is there.
Making the vocabulary yours
use activates the keywords as they ship. To attach project-wide instructions to
everything, import the specs instead and extend them:
// src/framework.psy
import { Agent as MorphicAgent, Skill as MorphicSkill } from "@psy/morphic"
export abstract spec Skill extends MorphicSkill as skill:
contract:
The specification in `spec/` is authoritative. Read it before changing
behaviour.
export abstract spec Agent extends MorphicAgent as agent:
contract:
Run the verification commands, and report honestly what passed.Your modules then use "./framework" rather than the package. Every skill now
inherits contract, which becomes a section in every generated artifact, from one
edit.
The same trick adds requirements:
export abstract spec Component extends MorphicComponent as component:
abstract owner: string
testing:
Every component ships with a rendering test and an interaction test.Every component must now declare an owner, and inherits a Testing section. This
is the single highest-leverage thing in Morphic and it is worth doing on day one.
One warning: do not use both the package and a local module that re-exposes
the same keyword. Activating one keyword twice is PSY3009.
What Morphic does not do
It does not generate anything. Not one byte. Turning a Morphic model into files is an adapter's job, which is deliberate: a different adapter could render these same declarations for a completely different platform without changing a line of Psy.
This section
- What Morphic Is — you are here.
- Skills, Agents And Commands — the working half, property by property.
- Specifying Software — how to describe your software so an agent can build it.
- concept — the ideas you have to understand.
- domain — a region of the problem, and what belongs to it.
- feature — behaviour, described from outside.
- component — a unit of implementation, and its invariants.
- reference — the rules that apply everywhere.
- What Gets Generated — sections, validation, and the exact file mapping.
- Shipping A Plugin — packaging it all as a Claude Code plugin.