Skip to content

LLM Skill

If you use an LLM to assist with writing configuration files — whether integrated in your IDE or at a website — you can give it the following skill to produce correct LPML. Click the copy button on the code block to grab the full instruction set.

For Claude Code, save this as .claude/skills/lpml/SKILL.md in your project. For other tools, paste it into your LLM’s system prompt, project instructions, or conversation context.

SKILL.md
---
name: lpml
description: LPML (LPC Markup Language) specification reference. Consult when reading, writing, editing, or validating .lpml files. Covers syntax, data types, string concatenation, spacey keys, file includes, multiline folding, and all extensions over JSON5.
---
# LPML (LPC Markup Language) Specification v1.0.0
LPML is a human-friendly data serialization format designed for MUD
configuration files. It extends JSON5 with LPC-environment-specific features.
## Design Goals
1. Easy to read and write by hand
2. Optional file includes for modular configs
3. Natural multiline strings without escape hell
4. Full JSON/JSON5 compatibility
5. Fast enough for config files (not hot paths)
## File Extension
The recommended extension is `.lpml`. Alternatives `.json` or `.json5` may be
used for editor syntax highlighting.
## Base Syntax (JSON5)
LPML inherits all JSON5 features:
### Comments
// Single-line comment
/* Multi-line
comment */
### Unquoted Keys
Keys can be written without quotes if they are valid identifiers:
{ name: "Gesslar", level: 10 }
### Trailing Commas
Permitted in objects and arrays:
{ a: 1, b: 2, }
[1, 2, 3,]
### Single-Quoted Strings
{ name: 'single quotes work too' }
### Number Formats
{
hex: 0xFF,
octal: 0o77,
binary: 0b1010,
decimal: 3.14,
leading_dot: .5,
trailing_dot: 5.,
plus_sign: +42,
}
## LPML Extensions
These features go beyond JSON5:
### Spacey Keys
An unquoted key can be almost anything, YAML-style. The parser reads everything
from the start of the key until the first `:`, then trims surrounding
whitespace — so spaces, hyphens, dots, digits, and UTF-8 letters are all valid:
{
hit points: 100,
max hit points: 120,
experience points: 1500,
admin-heal: "sound.wav",
café: "value",
}
The first `:` always ends the key (LPML differs from YAML here, which ends a key
only at a colon followed by whitespace). Quote a key only when it must contain a
literal colon:
{
"key: with colon": "value",
}
### String Concatenation
Adjacent string values automatically concatenate. The joining rule depends on
whether the preceding string ends with `\n`:
- If a string ends with `\n`, the next string concatenates **without** adding
a space.
- Otherwise, strings are joined with a single space.
This works across quote styles (double and single quotes can be mixed).
{
// These join with spaces (no trailing \n):
bio: "A seasoned adventurer from the West."
"Known for incredible fashion sense."
"Has a pet dragon named Sparky.",
// Result: "A seasoned adventurer from the West. Known for incredible fashion sense. Has a pet dragon named Sparky."
// Lines ending with \n concatenate WITHOUT a space:
poem: "Roses are red,\n"
"Violets are blue,\n"
"LPML is awesome,\n"
"And so are you.",
// Result: "Roses are red,\nViolets are blue,\nLPML is awesome,\nAnd so are you."
// Mixed: \n suppresses the space, no \n adds a space
help: "Usage: command [options]\n"
"\n"
"This command does something useful."
"It has multiple paragraphs.\n"
"\n"
"See 'help topics' for more info.",
// Result: "Usage: command [options]\n\nThis command does something useful. It has multiple paragraphs.\n\nSee 'help topics' for more info."
}
### Multiline Strings (Source Line Folding)
Actual newlines in the source (pressing Enter) are converted to spaces. Escape
sequences like `\n` remain as literal newline characters. This means you write
long strings naturally across source lines without worrying about embedded
newlines.
### File Includes
Values beginning with `#` followed by a path denote file includes.
{
stats: "#./stats.lpml",
inventory: "#./inventory.lpml",
database: "#./db-config.lpml",
}
Rules:
- A conforming implementation SHOULD replace the `#path` value with the parsed
contents of the referenced file.
- File includes are processed recursively (included files may themselves
contain includes).
- If a file cannot be found, an implementation SHOULD keep the include string
as its literal value.
- To produce a literal `#` at the start of a string (preventing include
processing), escape it: `\#`.
{
color_code: "\#FF0000", // Literal string "#FF0000", not a file include
}
## Data Types
### Primitives
{
string: "text",
number: 42,
float: 3.14,
boolean: true,
null: null,
}
### Arrays
Arrays support homogeneous, mixed-type, and nested elements with trailing
commas:
{
array: [1, 2, 3],
mixed: ["string", 42, true, null],
nested: [[1, 2], [3, 4]],
trailing: [1, 2, 3,],
}
### Objects (Mappings)
Objects support nesting and trailing commas:
{
simple: { x: 1, y: 2 },
nested: {
stats: { str: 10, dex: 15 },
},
trailing: { a: 1, b: 2, },
}
### Special Values
#### Infinity and NaN
`Infinity`, `-Infinity`, and `NaN` are valid values. In LPC, these map to
`undefined` (equivalent to `([])[0]`) because LPC does not have native
Infinity/NaN support.
{
inf: Infinity,
neg_inf: -Infinity,
nan: NaN,
}
#### MAX_INT and MAX_FLOAT
LPC-specific constants that support sign prefixes (`+`/`-`):
{
maxInt: MAX_INT,
minInt: -MAX_INT,
maxFloat: MAX_FLOAT,
minFloat: -MAX_FLOAT,
}
### Escape Sequences
Standard JSON escape sequences are supported in strings:
| Escape | Meaning |
|--------|---------|
| `\"` | Double quote |
| `\'` | Single quote |
| `\\` | Backslash |
| `\/` | Forward slash |
| `\b` | Backspace |
| `\f` | Form feed |
| `\n` | Newline |
| `\r` | Carriage return |
| `\t` | Tab |
| `\uXXXX` | Unicode character |
| `\#` | Literal `#` (prevents file include processing) |
## Differences from JSON5
| Feature | JSON5 | LPML |
|---------|-------|------|
| Comments | yes | yes |
| Trailing commas | yes | yes |
| Unquoted keys | yes | yes |
| Spacey keys | no | yes |
| Single quotes | yes | yes |
| Hex numbers | yes | yes |
| Octal/binary numbers | no | yes |
| MAX_INT/MAX_FLOAT | no | yes |
| String concatenation | no | yes |
| File includes | no | yes |
| Multiline folding | no | yes |
## Formatting Guidelines
- Keep lines within 80 columns. LPML files are MUD configuration data consumed
in terminal contexts where 80 columns is the norm.
- Break long string concatenation values across multiple lines to stay within
the limit.
- Break long arrays across multiple lines if they would exceed 80 columns.
## Complete Example
// character.lpml
{
name: "Gesslar",
title: "Wielder of Sharp Things",
// File includes
stats: "#./stats.lpml",
inventory: "#./inventory.lpml",
// Spacey keys
hit points: 100,
max hit points: 120,
experience points: 1500,
// String concatenation (space-joined)
bio: "A seasoned adventurer from the West."
"Known for incredible fashion sense."
"Has a pet dragon named Sparky.",
skills: {
combat: 85,
magic: 60,
social: 75,
},
}
## Item Configuration Example
// cat_fur.lpml
{
id: ["fur"],
additional ids: ["hide", "piece"],
adj: ["cat", "soft"],
name: "cat fur",
short: "a piece of cat fur",
long: "This is a soft piece of fur from a wild cat."
"It could be useful for crafting.",
mass: 20,
material: ["fur"],
properties: {
autovalue: "yes",
crafting material: "yes",
},
}
## Modular Configuration Example
// main.lpml
{
game: {
name: "My MUD",
port: 4000,
database: "#./db-config.lpml",
features: "#./features.lpml",
discord: "#./discord-config.lpml",
},
}
// db-config.lpml
{
host: "localhost",
port: 5432,
name: "mud_db",
pool_size: 10,
}
## Credits
LPML was created by Gesslar, based on the JSON5 specification. Licensed under
the Unlicense (public domain).

The base skill above covers the LPML format itself. Most projects benefit from appending additional sections that tell the LLM how you want it applied. Below are some common conventions you can add to your skill.

If your project uses a known schema, describe it so the LLM can produce valid files without guessing.

## Project Schema
Our item configuration files use the following structure:
{
id: ["primary_id"],
additional ids: ["alias1", "alias2"],
adj: ["adjective1", "adjective2"],
name: "display name",
short: "a short description",
long: "A longer description of the item."
"Can use string concatenation for readability.",
mass: 0,
material: ["material_type"],
properties: {
// Item-specific properties
}
}

If your project has formatting conventions, state them explicitly.

## Style Preferences
- Always use trailing commas
- Use spacey keys for multi-word property names
- Use string concatenation for values longer than 72 characters
- Add a comment header at the top of each file describing its purpose
- Use relative file includes (#./) rather than absolute paths

If your project uses file includes to organize configs, describe the expected structure.

## File Organization
Our configuration is split across files using includes:
- main.lpml — Top-level entry point
- db-config.lpml — Database connection settings
- features.lpml — Feature flags and toggles
- discord-config.lpml — Discord integration settings
Each sub-config is included from main.lpml:
{
game: {
name: "My MUD",
database: "#./db-config.lpml",
features: "#./features.lpml",
discord: "#./discord-config.lpml",
}
}