Claude-skill-registry container
Intermediate scope for inheritance — like OpenLaszlo's <node>
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/container" ~/.claude/skills/majiayu000-claude-skill-registry-container && rm -rf "$T"
manifest:
skills/data/container/SKILL.mdsource content
Container
Intermediate scopes that provide inheritance without being navigable rooms.
Containers are directories that define shared properties for their children, without themselves being places you can "go to."
The OpenLaszlo Inspiration
In OpenLaszlo (Don Hopkins' earlier work!),
<node> was a fundamental building block:
<!-- OpenLaszlo: <node> provides inheritance without visual layout --> <node name="mazeDefaults"> <attribute name="isDark" value="true"/> <attribute name="hasDanger" value="true"/> </node> <view extends="mazeDefaults"> <!-- Inherits isDark, hasDanger --> </view>
MOOLLM's
CONTAINER.yml does the same for adventure directories:
# maze/CONTAINER.yml container: name: "The Twisty Maze" inherits: is_dark: true is_dangerous: true grue_rules: can_appear: true
All rooms inside
maze/ automatically inherit these properties!
Container vs Room vs Meta
| Type | File | Navigable? | Inherits to children? |
|---|---|---|---|
| Room | | ✅ Yes | ❌ No |
| Container | | ❌ No | ✅ Yes |
| Meta | | ❌ No | ❌ No (just metadata) |
Use Container when:
- You want to define shared properties
- Children should inherit automatically
- The directory itself is not a place
Use Room when:
- The directory is a navigable location
- It has exits and can be entered
Use .meta.yml when:
- Just declaring "this is a system directory"
- No inheritance needed
Inheritance Rules
Cascade Down
Properties in
inherits: flow to ALL descendants:
maze/ ├── CONTAINER.yml # inherits: { is_dark: true } ├── room-a/ │ └── ROOM.yml # Inherits is_dark: true ├── room-b/ │ └── ROOM.yml # Inherits is_dark: true └── deep/ └── CONTAINER.yml # Can add MORE inherits └── room-c/ └── ROOM.yml # Inherits from BOTH containers!
Override by Redefining
Children can override inherited values:
# maze/room-f/ROOM.yml room: name: "The Treasure Chamber" is_dark: false # Override! This room has magical light
Merge, Don't Replace
For objects and arrays, inheritance MERGES:
# maze/CONTAINER.yml container: inherits: rules: - "Grues patrol in darkness" # maze/room-g/ROOM.yml room: rules: - "This room has a pit trap" # ADDS to inherited rules
Result: room-g has BOTH rules.
Defaults vs Inherits
| Field | Purpose |
|---|---|
| Properties that children GET automatically |
| Values to use IF a child doesn't define them |
container: # Every child room IS dark (forced) inherits: is_dark: true # If a room doesn't define atmosphere, use this defaults: room: atmosphere: "damp and musty"
Use Cases
Maze with Grue Rules
# maze/CONTAINER.yml container: name: "The Twisty Maze" description: "Passages all alike... or are they?" inherits: is_dark: true is_dangerous: true grue_rules: can_appear: true safe_with_light: true rules: - "No teleportation" - "Breadcrumbs disappear after 3 turns" - "Echoes alert nearby rooms" ambient: sound: "dripping water" smell: "wet stone" temperature: cold
Animal Character Category
# characters/animals/CONTAINER.yml container: name: "Animal Characters" description: "Non-human beings with souls" inherits: type: animal has_instincts: true defaults: character: can_speak_human: false pet_able: true diet: omnivore
Kitchen Appliances
# kitchen/appliances/CONTAINER.yml container: name: "Kitchen Appliances" inherits: type: appliance requires_power: true defaults: object: breakable: true fixable_with: "wrench"
Resolution Order
When looking up a property:
- Self — Check the object/room itself
- Parent Container — Check
in parent dirCONTAINER.yml - Grandparent Container — Keep going up
- Adventure Defaults —
defaultsADVENTURE.yml - Prototype — The skill template
maze/deep/room-c/ROOM.yml ↓ inherits from maze/deep/CONTAINER.yml ↓ inherits from maze/CONTAINER.yml ↓ inherits from ADVENTURE.yml (if it has defaults) ↓ inherits from skills/room/ROOM.yml.tmpl
Linter Behavior
The linter recognizes
CONTAINER.yml:
📂 Phase 1: Discovery Found: 36 rooms, 54 objects, 6 characters Found: 2 containers # NEW!
Containers suppress the "missing type declaration" warning:
# Before: maze/ triggers warning ⚠️ Directory has room children but no ROOM.yml # After: maze/CONTAINER.yml exists ✅ maze/ is a container (not a room)
Related Patterns
- Prototype Inheritance (Self/JavaScript) — Objects inherit from prototypes
- Lexical Scope (Lisp/JavaScript) — Inner scopes access outer variables
- Cascading (CSS) — Styles flow from parent to child
- XML Namespaces — Context flows through the tree
Credits
- OpenLaszlo — The
element as non-visual scope<node> - Self — Prototype inheritance without classes
- CSS — The cascade as inheritance mechanism
- Don Hopkins — For remembering OpenLaszlo! 🎉