Example Projects
Runnable Psy projects, all of them compiled on every check so none of them can drift.
Everything in examples/ is compiled by psy check on every run, so nothing here
can quietly stop being true.
paint
The whole Morphic vocabulary on one project: a simple raster painting program, described in Psy alongside the skills and agent that build it.
paint/
concepts/ Paint, and the ideas that span its domains
references/ Voice — how the interface addresses people
domains/ Canvas, Tools, Files
components/ CanvasSurface, ToolPalette, ColorPicker
features/ Pencil, Eraser, FloodFill, SaveLoad
skills/ CanvasRules, ImplementTool, WriteInterfaceCopy
agents/ BuildPaintOne folder per kind, one declaration per file, each re-exported through an
index.psy.
The split is the point. The first five folders say what the program is; the last
two say how to work on it. ImplementTool names Tools, ToolPalette and
ColorPicker in its context, so an agent adding a tool is handed the canvas
rules rather than told to go and find them.
psy build compiles it into paint/.claude/, where every definition becomes a
skill and gets loaded when it becomes relevant. See
Specifying Software.
deployment
Psy as an ordinary configuration language. No frameworks, no keywords, just specs.
export const Region = eu-west-1
export const DefaultReplicas = 2
export spec BaseService:
region: Region
replicas: DefaultReplicas
resources:
cpu: 500m
memory: 512Mi
tags:
- managed
- psy
export spec Observability:
tags:
- metrics
- traces
resources:
memory: 768Mi
export spec Api extends BaseService, Observability:
name: api
replicas: 4
resources:
+ super
tags:
+ super
- publicpsy inspect Api{
"name": "api",
"replicas": 4,
"resources": { "cpu": "500m", "memory": "512Mi" },
"tags": ["managed", "psy", "metrics", "traces", "public"],
"region": "eu-west-1"
}Api.resources is { cpu: 500m, memory: 512Mi } — BaseService outranks
Observability, so its memory wins the conflict. Api.tags is
[managed, psy, metrics, traces, public].
This is the example the data output section uses.
custom-framework
Keyword definition and use, in about thirty lines total.
// framework.psy
export abstract spec Pipeline as pipeline:
abstract description: string
abstract stages: Stage[]
export abstract spec Stage as stage:
abstract description: string
abstract command: string
retries: 0// main.psy
use "./framework"
export stage Install:
description: Install dependencies
command: npm install
export stage Test:
description: Run the test suite
command: npm test
retries: 1
export pipeline Ci:
description: The continuous integration pipeline
stages:
- Install
- Testpsy inspect CiCi (main.psy)
keyword: pipeline
precedence: main.psy#Ci > framework.psy#Pipeline
description = "The continuous integration pipeline"
stages = [Install, Test]stages is typed Stage[], so the compiler checks that Install and Test
really are stages. In the IR those entries are spec references, not strings. See
Your Own Keywords.
Fixture projects
fixtures/valid/ and fixtures/invalid/ are small single-purpose projects the
test suite drives. Each carries a fixture.json naming the specification rules it
validates:
{
"rules": ["MultipleInheritance", "ParentPrecedence", "PlainSuper", "ComposedSuper"],
"expect": {
"specs": { "Child": { "foo": "fromA" } },
"linearization": { "Child": ["Child", "A", "B", "C"] }
}
}The invalid ones name the diagnostic they must produce:
{ "rules": ["NoCircularInheritance"], "expect": { "diagnostics": ["PSY3006"] } }A test asserts that every rule name exists in spec/, and that every expected
diagnostic code has a diagnostic-rule describing it. That is what keeps the
trace from specification rule → test → implementation honest. See
Psy Describes Psy.