Claude-skill-registry inventory
You carry pointers. When you set them down, they become real.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/inventory" ~/.claude/skills/majiayu000-claude-skill-registry-inventory && rm -rf "$T"
skills/data/inventory/SKILL.mdINVENTORY
"Carry pointers or values. Set them down, they become real."
The universal protocol for carrying, storing, and transferring objects. Applies to ANY container: characters, bags, rooms, artifacts, vehicles.
Files in This Skill
— Full protocol documentation (this file)SKILL.md
— Human landing pageREADME.md
— Interface definitionCARD.yml
— Standalone inventory templateINVENTORY.yml.tmpl
Core Philosophy
Inventory holds two kinds of things: POINTERS and VALUES.
Your character's home directory is their "bag." Items in it are:
| Type | Weight | What You Have |
|---|---|---|
| Pointer | 0 | Reference to where something lives |
| Value | varies | Text, number, array, object, subtree |
| Object | item.weight | Deep copy of the actual thing |
| Fungible | per-item | Stack with count, no individual tracking |
Pointers are lightweight: You don't carry the brass lantern. You carry a path to where it lives.
Values are direct: You can also carry raw text, numbers, arrays, entire subtrees — any YAML/JSON value.
When you drop either kind, it gets boxed into a YAML file with its own existence.
Universal Application
Inventory applies to ANY container, not just characters:
| Container | Has Inventory? | Example |
|---|---|---|
| Character | ✓ | Palm's backpack |
| Bag | ✓ | Bag of holding |
| Room | ✓ (implicit) | Objects in the pub |
| Chest | ✓ | Treasure chest contents |
| Vehicle | ✓ | Cargo hold |
| Artifact | ✓ | Ring with stored spell |
Embedding inventory:
# In CHARACTER.yml (most common) inventory: refs: - pub/bar/brass-lantern.yml fungibles: - { proto: economy/gold.yml, count: 500 } # Or standalone INVENTORY.yml for any container # bag-of-holding/INVENTORY.yml inventory: refs: - kitchen/cookie-jar.yml#cookie - street/acme-catalog.yml objects: - { id: magic-sword, name: "Vorpal Blade", weight: 3 }
Reference Types
References can point into ANY file type. A reference is just a string that locates something.
Pointer Syntax
| Syntax | Points To | Example |
|---|---|---|
| Whole YAML file | |
| Section by id | |
| Nested path | |
| Markdown heading | |
| JSON pointer | |
| Search pattern | |
| Line number | |
| Line range | |
The pointer is the reference. It can point to:
- A prototype in a YAML file
- A section embedded in a larger file
- A heading in a markdown document
- A JSON field
- Even a line in source code
Unified Addressing
This pointer syntax is shared across ALL systems:
| System | Uses Pointers For |
|---|---|
| Inventory | What you carry () |
| Location | Where you are () |
| Postal | Where to deliver mail () |
| Structural Editing | Where to PEEK/POKE |
Same syntax, everywhere. Mail a letter to a function. Stand on a JSON key. POKE a value into a YAML path. It's all the same address space.
Not all addresses make sense — but they're all valid. You can stand on
package.json#/devDependencies/vitest. Weird? Sure. Works? Yes.
Reference Structure
Simple reference (just a string):
inventory: refs: - pub/bar/brass-lantern.yml - street/acme-catalog.yml#portable-hole
Rich reference (with metadata):
inventory: refs: - ref: pub/bar/brass-lantern.yml acquired: "2026-01-23T10:00:00Z" condition: "good" note: "Found in the cellar"
Location as Pointer (Code as Space)
The pointer syntax is bidirectional. Not just "what you carry" — also "where you ARE."
Any object's
location: field uses the same pointer syntax. This means characters, artifacts, and entities can exist inside any file type:
# Character standing on a TypeScript function name: Alice location: src/lib/utils.ts#fetchData note: "Reviewing this function with the team" # Artifact placed at a specific line range name: Bug Marker location: src/auth/login.ts:45-67 note: "The authentication bug lives here" # Entity inside a JSON config name: Config Watcher location: package.json#/dependencies/svelte note: "Monitoring version changes"
Code Review as Adventure
A hacking party can literally stand inside source code:
# The review party participants: - { name: Alice, location: "src/api/handler.ts#processRequest" } - { name: Bob, location: "src/api/handler.ts#validateInput" } - { name: Carol, location: "src/api/handler.ts:89-95" } # The problematic lines session: topic: "Why does validation fail on unicode input?" room: "src/api/handler.ts" context: "Standing around the processRequest function"
What This Enables
| Use Case | Location Pointer |
|---|---|
| Code review | Stand on functions, discuss them |
| Bug hunting | Place markers at suspicious lines |
| Pair programming | Multiple characters at same location |
| Architecture tours | Walk through a codebase as rooms |
| Documentation | Annotate code with character observations |
The codebase becomes a dungeon. Files are rooms. Functions are objects. Line ranges are specific spots. Characters can go there, look around, leave notes, argue about what they see.
Pickup Modes
Two fundamentally different ways to pick something up:
TAKE REF — Lightweight Pointer
> TAKE REF TO brass-lantern You now have a reference to the brass lantern. (weight: 0)
What happens:
- Create pointer in your inventory
- Object stays where it is
- Object's
field updates:locationlocation: "characters/don/inventory" - You have zero weight added
Use when:
- Just need access to it
- Don't want to carry weight
- Shared resource (dispenser, catalog)
- Can't physically move it (too heavy)
TAKE OBJECT — Deep Copy
> TAKE OBJECT cookie You pick up the cookie. (weight: 0.1)
What happens:
- Copy entire object into your inventory
- Your file gets bigger (embedded object)
- Weight added to your load
- Original MAY stay or be deleted (your choice)
Use when:
- Small object, negligible weight
- Want to OWN it completely
- Need to modify it freely
- Don't want inheritance chain
Picking Up Boxed Items
GOLDEN RULE: Once boxed, always boxed.
If something already has a file (is "boxed"), picking it up preserves everything:
# kitchen/acme-catalog-001.yml already exists with: # inherits: street/acme-catalog.yml # annotations: ["circled portable hole"] # dropped_by: palm # Don picks it up AS OBJECT: # File moves to: characters/don/acme-catalog-001.yml # All annotations preserved! # Don picks it up AS REF: # inventory: [ref: "kitchen/acme-catalog-001.yml"] # File stays in kitchen, Don just has pointer.
Drop Modes
Three fundamentally different ways to put something down:
DROP AS BOX — Create New File
> DROP brass-lantern AS BOX Created: kitchen/brass-lantern-001.yml
What happens:
- Create new YAML file at destination
- New file
from your ref's targetinherits: - Adds boxed metadata (who, when, where)
- You can KEEP your original ref (sharing) or consume it
- Boxed item now has its own existence and local state
Boxing creates an instance:
# kitchen/brass-lantern-001.yml object: inherits: "pub/bar/brass-lantern.yml" # Instance metadata instantiated_at: "2026-01-23T14:00:00Z" instantiated_by: "don" instantiated_from: "inventory" # Local state (can now diverge from prototype) condition: "slightly worn" inscribed: "Property of Don"
DROP AS BEAM — Move Actual File
> DROP brass-lantern AS BEAM File moved to: garden/brass-lantern.yml
What happens:
- Actual file relocates to destination
- No inheritance created
- All properties preserved (it's the same file)
- You NO LONGER have it
- Origin is now empty (file moved)
Use when:
- Giving something away permanently
- Moving heavy objects
- Avoiding inheritance chains
- The thing should BE here now
DROP INTO — Insert in Container List
> DROP cookie INTO treasure-chest Cookie added to treasure-chest.yml contents list.
What happens:
- Target file has a list (contents, items, inventory)
- Your item inserted into that list
- No new file created
- Packed storage in existing file
Container file structure:
# treasure-chest.yml object: name: "Treasure Chest" contents: - { id: gold-coins, proto: economy/gold.yml, count: 100 } - { id: ruby, name: "Ruby", weight: 0.5 } - ref: magic-scroll.yml # ← your item inserted here
Boxing Protocol
Boxing (like Java boxing) — instantiating a pointer into a real file with identity.
When you have a lightweight pointer and DROP AS BOX, the reference gets boxed — instantiated into a YAML file that inherits from the pointer's target. Like Java's
int → Integer, but here it's pointer → YAML file with identity.
The Journey of an Object
# THE JOURNEY OF A CATALOG: # 1. ORIGIN: street/acme-catalog.yml (prototype, dispenser) # 2. DON TAKES REF at street: don.inventory: [ref → street/acme-catalog.yml] # (No file created yet, just pointer) # 3. DON DROPS AS BOX in kitchen: # Creates: kitchen/acme-catalog-001.yml # inherits: street/acme-catalog.yml # boxed_by: don, annotations: ["circled hole"] # Don's ref is consumed. # 4. PALM TAKES AS OBJECT from kitchen: # File moves: palm.inventory/acme-catalog-001.yml # All annotations preserved! # Kitchen is now empty. # 5. PALM DROPS AS BEAM in study: # File moves: study/acme-catalog-001.yml # Still has Don's annotations! # Palm no longer has it. # 6. BUMBLEWICK TAKES AS REF from study: bumblewick.inventory: [ref → study/acme-catalog-001.yml] # File stays in study. # 7. BUMBLEWICK DROPS AS BOX in garden: # Creates: garden/acme-catalog-002.yml # inherits: study/acme-catalog-001.yml # boxed_by: bumblewick, annotations: ["added doodles"] # Now there are TWO catalogs: # - study/acme-catalog-001.yml (Don's original box) # - garden/acme-catalog-002.yml (Bumblewick's copy) # Full provenance chain preserved at every step!
Boxing Golden Rules
- Once boxed, always boxed — Instances travel intact
- Instances accumulate history — Each handler can add provenance
- Inheritance chains — Instances can inherit from instances
- Local state divergence — Instances can override their prototype
Transport Modes
For heavy objects you can't carry:
BEAM / TRANSPORTER
Use a reference as a targeting system:
> TAKE REF TO grand-piano You have a reference to the grand piano. (weight: 0) > GO concert-hall You arrive at the concert hall. > BEAM grand-piano HERE *shimmer* Piano materialized! concert-hall/grand-piano.yml created.
How it works:
- Take lightweight REF to heavy object
- Travel to destination (carrying only the pointer)
- BEAM command uses ref as target
- Object teleported/moved to your location
- Ref consumed, you have actual object here
FORKLIFT Mode
Mechanical assistance for moving heavy objects:
> SUMMON FORKLIFT Forklift arrives. > LOAD bronze-statue ONTO forklift Statue loaded. > GO garden You move to garden, forklift follows. > UNLOAD bronze-statue AS BEAM Statue placed in garden/bronze-statue.yml
Fungibles
Fungible items are identical and interchangeable. No individual tracking — just a count.
Counts can be fractional! 3.5 gold coins, 0.25 moolah, 2.7 kg of flour — why not?
Fungible Stack Structure
inventory: fungibles: - { proto: economy/gold.yml, count: 500 } - { proto: economy/moolah.yml, count: 3.50 } # Fractional! - { proto: food/cookie.yml, count: 12 } - { proto: food/flour.yml, count: 2.7, unit: kg } # Continuous - { proto: materials/iron-ore.yml, count: 45, quality: high }
Operations
| Operation | Command | Effect |
|---|---|---|
| Add | Pick up 100 gold | |
| Remove | Pay 50 gold | |
| Split | Split pile | Create two stacks from one |
| Merge | Combine piles | Add counts together |
FUNGIFY — Convert to Stack
> FUNGIFY gold-pile 3 unique gold coins → 1 fungible stack (count: 3) WARNING: Individual properties lost!
What you lose:
- Individual conditions (fair, good, mint)
- Unique properties (rare, cursed)
- Provenance (who owned it before)
- Sentimental value
Partial FUNGIFY:
> FUNGIFY gold-pile KEEPING rare 2 coins fungified, 1 rare coin kept unique.
UNFUNGIFY — Create Individuals
> UNFUNGIFY gold COUNT 5 5 gold coins created as individual items. Each can now have unique properties.
Dispensers
A dispenser lets you TAKE copies without depleting the original.
| Type | What You Get | Example |
|---|---|---|
| Ref Dispenser | Lightweight pointer | Catalog rack, brochure stand |
| Instance Dispenser | New object file | Cookie jar, vending machine |
| Fungible Dispenser | Add to stack | Gold pile, ore vein |
Dispenser config:
object: name: "Cookie Jar" type: dispenser dispenser_config: mode: instance # ref | instance | fungible template: cookie # What to dispense stock: 12 # null = infinite respawn: daily # How stock replenishes templates: cookie: name: "Cookie" prototype: food/cookie.yml weight: 0.1
Stamp Pads
Refs as instance factories — like Factorio blueprints.
stamp_pad: prototype: furniture/chair.yml mode: counted # counted | unlimited | charged uses_remaining: 10 instance_defaults: condition: new placed_by: "{player.name}"
Stamping:
> SELECT chair-stamp Chair Stamp selected. [10 remaining] > STAMP AT corner *plop* Chair appears in corner. corner/stamped-chair-001.yml created. [9 remaining]
Structural Editing
The pointer syntax is a universal structural editing protocol for YAML and JSON. Same addressing, same operations, syntax-independent.
The Insight
If you can TAKE a subtree, you can PEEK at it. If you can DROP a subtree, you can POKE it. If you can move subtrees between files, you can edit structure.
Pointers are addresses. Addresses enable operations.
Operations
| Operation | Command | Effect |
|---|---|---|
| PEEK | | Read value at path |
| POKE | | Write value at path |
| SNIP | | Extract subtree (leaves hole) |
| PULL | | Extract into inventory or new file |
| SPLICE | | Insert into list/array |
| APPEND | | Add to end of list |
| SET | | Create or overwrite key |
| DELETE | | Remove key entirely |
| CLEAR | | Set to null/empty |
| DUPLICATE | | Copy subtree |
| MOVE | | Relocate subtree |
Examples
# PEEK — read a value > PEEK config.yml#settings.timeout 30 # POKE — write a value > POKE config.yml#settings.timeout = 60 Done. # SNIP — extract and remove > SNIP characters.yml#npcs.henk Henk extracted to inventory. (hole left in npcs) # PULL — extract to file > PULL characters.yml#npcs.henk TO henk.yml Created henk.yml with Henk's data. # SPLICE — insert into list > SPLICE {name: "Cookie", weight: 0.1} INTO chest.yml#contents Inserted at position 0. # APPEND — add to end > APPEND "new item" TO inventory.yml#refs Added to refs list. # SET — create or overwrite > SET room.yml#visited = true Set visited to true. # DELETE — remove key > DELETE character.yml#temp_data Removed temp_data. # DUPLICATE — copy subtree > DUPLICATE template.yml#npc_base TO characters.yml#npcs.bob Bob created from npc_base template. # MOVE — relocate subtree > MOVE old.yml#settings TO new.yml#config Settings moved from old.yml to new.yml#config.
Syntax Independence
These operations work identically on YAML and JSON:
| Source | Target | Works? |
|---|---|---|
| YAML | YAML | ✓ |
| JSON | JSON | ✓ |
| YAML | JSON | ✓ (auto-convert) |
| JSON | YAML | ✓ (auto-convert) |
The pointer addresses structure, not syntax. The underlying tree is the same whether serialized as YAML or JSON.
Nested Paths
# Deep addressing > PEEK game.yml#characters.party.members[0].inventory.weapons[2] "Vorpal Sword" # Wildcards for bulk operations > DELETE config.yml#users.*.temp_tokens Deleted temp_tokens from all users. # Conditional addressing > PEEK npcs.yml#[?(@.faction=="rebels")] [all NPCs where faction is "rebels"]
Atomic Operations
For complex edits, use transactions:
# BEGIN/COMMIT for atomic multi-step edits > BEGIN EDIT game.yml > SET #player.health = 100 > APPEND "heal-potion" TO #player.inventory > DELETE #player.status.poisoned > COMMIT Atomic edit applied. # ROLLBACK on failure > BEGIN EDIT game.yml > SET #player.gold = -500 # Invalid! > ROLLBACK Edit cancelled.
Integration with Inventory
Structural editing IS inventory manipulation:
| Inventory Action | Structural Equivalent |
|---|---|
| TAKE REF | PEEK (get address) |
| TAKE OBJECT | SNIP (extract copy) |
| DROP AS BOX | PULL to new file |
| DROP INTO | SPLICE/APPEND |
| BEAM | MOVE |
Same protocol, different metaphors. Characters "pick up" and "drop" things. Editors "snip" and "splice" structure. Both are moving subtrees via pointers.
Commands
| Command | Action |
|---|---|
| Pick up (default: smart mode) |
| Pick up as pointer |
| Pick up as deep copy |
| Put down (default: smart mode) |
| Create new file with inheritance |
| Move actual file |
| Insert into list |
| Teleport without carrying |
| List carried items |
| Show limits and usage |
| Convert to fungible stack |
| Convert to individual items |
Smart Defaults
When you don't specify mode, the system chooses:
TAKE defaults:
| Situation | Default Mode |
|---|---|
| From dispenser | REF (repeatable) |
| Boxed item | OBJECT (preserve annotations) |
| Heavy item | REF (can't carry) |
| Small unique item | OBJECT (don't leave behind) |
DROP defaults:
| Situation | Default Mode |
|---|---|
| Have reference | BOX (create instance) |
| Have object, giving away | BEAM (transfer) |
| Have object, sharing | BOX (keep original) |
| In your own space | BEAM (organizing) |
Weight and Capacity
capacity: max_weight: 45 # Total carrying capacity max_bulk: 10 # Volume limit refs_free: true # References don't count! current: weight: 12 # Sum of objects bulk: 3 refs: 15 # Unlimited pointers
Why refs are free: A reference is just a string — a path to something. It costs nothing to carry a path. The weight only comes when you carry the actual thing.
Dovetails With
- ../character/ — Characters have inventories
- ../object/ — Objects can be items or containers
- ../room/ — Rooms implicitly contain objects
- ../container/ — Container abstraction
- ../prototype/ — References point to prototypes
- ../postal/ — Mail delivery uses inventory transfer
- ../logistic-container/ — Factorio-style logistics
- ../buff/ — Temporary effects on items
- ../economy/ — Currency as fungible inventory
Protocol Symbols
| Symbol | Meaning |
|---|---|
| Invoke this skill |
| Lightweight pointer pickup |
| Deep copy pickup |
| Create inheriting file |
| Move actual file |
| Convert to stack |
| Pointer → instance (like Java boxing) |
| Move without carrying |
"Pointers and values — carry them light, drop them real."