npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gulluth/sigil

v0.1.9

Published

SIGIL (Sigil Is Generative Interpretive Language) - A minimalist YAML-based DSL for worldbuilding generators with automatic list merging and plugin architecture

Readme

EXPERIMENTAL SOFTWARE

SIGIL is experimental software, and should be treated as such. I am frequently making breaking API changes to tune SIGIL to the way I am expecting it to operate.

You have been warned!

SIGIL

Sigil Is Generative Interpretive Language

A minimalist YAML-based DSL for creating powerful random generators. Perfect for game development, creative writing, worldbuilding, and any application that needs procedural content generation.

What is SIGIL?

SIGIL transforms simple YAML lists into sophisticated random generators with intelligent text processing, automatic content merging, and flexible template syntax. Designed for both browser and Node.js environments.

Installation

npm install @gulluth/sigil

Quick Start

import { SigilEngine } from '@gulluth/sigil';

const engine = new SigilEngine();
await engine.loadData('./data/my-data.yaml');

// Generate content from templates
const result = engine.generate('my_template');
console.log(result);

Core Features

  • YAML-based data structure with automatic list merging
  • Hierarchical organization using dot notation
  • Weighted randomization with custom probabilities
  • Rich template syntax with inline processing
  • Text formatting modifiers for proper grammar
  • Graceful error handling with missing data
  • Browser and Node.js support for flexible deployment

Sigil Reference

SIGIL uses symbolic characters called sigils to define generation behavior. Each sigil has a specific meaning and purpose within templates:

Core Sigils

| Sigil | Name | Purpose | Example | | ----- | -------------------- | ----------------------------- | ----------------------------------- | | [] | Reference Sigil | Access lists and tables | [device] → "scanner" | | {} | Inline Sigil | Inline processing container | {red\|blue} → "red" | | \| | OR Sigil | Choose one option | {this\|that} → "this" | | & | AND Sigil | Combine multiple selections | {red&large} → "redlarge" | | ^ | Weight Sigil | Control selection probability | laser rifle ^2 → 2x more likely | | ? | Optional Sigil | Random inclusion | [device?] → may or may not appear | | ! | Exclusion Sigil | Filter out items | [device!broken] → working devices | | * | Repetition Sigil | Repeat selections | [component*3] → 3 components | | . | Modifier Sigil | Apply text transformations | [name.capitalize] → "John" |

Special Patterns

| Pattern | Purpose | Example | | ---------------- | ------------------- | ------------------------------------------- | | {a} | Indefinite articles | {a} [item] → "an apple" | | {1-10} | Number ranges | {1-10} → random number 1-10 | | table.subtable | Hierarchical access | [shape.triangle] → from triangle subtable |

Sigil Combinations

Sigils can be combined for complex behavior:

  • [device*{2-4}?] - Optionally generate 2-4 devices
  • [material!radioactive.capitalize] - Capitalized material, excluding radioactive
  • {[condition]&[device]} - Combine condition and device selections

Sigil Precedence and Evaluation Order

  • AND (&) vs Optional (?): When AND and optional are combined (e.g., {[a]&[b]?}), AND takes precedence. All referenced elements are always included; optionality is ignored in this context.
  • Weights and Repetition: When using both weights and repetition (e.g., [item^2*3]), weights are applied first. Each repetition is an independent draw from the weighted pool.

See the Error Handling Guide for more details and examples.

Complete Syntax Reference

Basic Templates

Reference lists using square brackets:

templates:
  basic_item: "[condition] [device]"

Weighted Lists

Control probability using ^ notation:

devices:
  - laser rifle ^2      # 2x more likely
  - plasma torch        # default weight (1)
  - scanner ^0.5        # half as likely

Hierarchical Selection

Use dot notation for organized data:

shape:
  quadrilateral:
    - square
    - rectangle
  triangle:
    - equilateral
    - isosceles

# Select from subcategory
templates:
  room: "The [shape.quadrilateral] room"

Inline Randomization

OR Selection - Pick one option:

templates:
  greeting: "Hello {there|friend|stranger}"

AND Combination - Combine from two lists:

# Descriptive combinations
templates:
  combo: "A {red&dwarf} object"  # e.g., "A reddwarf object"

# Compound word generation (names, terms)
name_prefixes:
  - Zyx
  - Nex
  - Vor
  - Keth

name_suffixes:
  - on
  - ax
  - prime
  - core

templates:
  survivor_name: "{[name_prefixes]&[name_suffixes]}"  # e.g., "Zyxon", "Nexcore"

Mixed References - Combine lists and inline options:

templates:
  mixed: "A {[color]|[pattern]|striped} design"

Number Ranges - Generate random numbers:

templates:
  quantity: "Found {1-10} coins"
  precise: "Exactly {2.5-7.3} meters"

Advanced Features

Optional Content - Random inclusion using ?:

templates:
  item: "[device] [modification?]"  # Modification may or may not appear

Exclusion Filters - Remove items using !:

templates:
  working_device: "[device!broken]"  # All devices except broken ones

Repetition - Repeat selections using *:

templates:
  treasure: "[component*{2-4}]"  # Generates 2-4 components

Text Formatting

Indefinite Articles - Automatic a/an:

templates:
  description: "{a} [shape]"  # "an octagon" or "a square"

Chained Modifiers (Left-to-Right order)

You can chain multiple modifiers using dot notation, e.g. [table.capitalize.lowercase]. Modifiers are applied in left-to-right order: the leftmost modifier is applied first, and the rightmost is applied last. This matches the order you see in the template and is the most intuitive for users.

Example:

templates:
  fancy_name: "[name.capitalize.lowercase]"
  # This will first capitalize the name, then lowercase the result.

Supported modifiers:

  • capitalize — Capitalize the first letter
  • lowercase — Convert all letters to lowercase
  • pluralForm — Pluralize the word
  • markov — Generate text using Markov chains

Markov Generation - AI-style text from training data:

templates:
  generated_callsign: "[survivor_names&settlements.markov]"

Data Organization

Automatic List Merging

Lists with the same name from different files are automatically combined:

# post-apocalypse.yaml
devices:
  - laser rifle
  - plasma cannon

# Result: All devices available together for genre blending

File Structure

Organize your data across multiple YAML files:

project/
├── data/
│   ├── devices.yaml
│   ├── survivors.yaml
│   └── settlements.yaml
└── generator.js

YAML Structure Approaches

Choose the organizational style that best fits your content complexity.

Flat Structure (Simple Lists)

Perfect for straightforward content:

# simple-data.yaml
entities:
  - radiation mutant ^2
  - scavenger android ^1.5
  - malfunctioning drone

locations:
  - abandoned facility ^2
  - irradiated wasteland
  - underground bunker

templates:
  encounter:
    - "You detect [sounds] echoing from the [locations]"
    - "A [atmosphere] [entities] prowls nearby"

Hierarchical Structure (Organized Categories)

Better for complex, organized content:

# organized-data.yaml
vessel:
  type:
    - transport ^2
    - interceptor
    - cargo hauler ^3
  status:
    - operational
    - damaged ^2
    - derelict ^1.5

templates:
  vessel_description: "A [vessel.status] [vessel.type]"

Error Handling & Reliability

SIGIL is designed with robustness in mind and includes comprehensive error handling:

  • Defensive programming: Attempts to return valid strings even with malformed syntax
  • Graceful degradation: Missing data typically returns placeholder text
  • Recursion limits: Includes protection against circular references
  • Unicode support: Handles emojis, accented characters, and special symbols

Complete Error Handling Guide →

Common Use Cases

  • Game Development: Procedural content, random events, character generation
  • Creative Writing: Plot generators, character traits, world details
  • Tabletop RPGs: Monsters, loot, NPCs, dungeon rooms, random encounters
  • Educational Tools: Quiz questions, example datasets, learning scenarios
  • Testing Data: Realistic mock data generation for applications

API Reference

Quick Reference

import { SigilEngine, loadSigilData } from '@gulluth/sigil';

// Single file
const engine = new SigilEngine();
await engine.loadData('./data/my-data.yaml');

// Multi-file (Node.js)
const data = loadSigilData(['./core.yaml', './expansion.yaml']);
const engine = new SigilEngine(data.lists);

const result = engine.generate('my_template');
console.log(result);

Key Methods:

  • loadData(filePath) - Load single YAML file (Node.js)
  • loadSigilData(filePaths[]) - Load and merge multiple files (Node.js)
  • generate(templateName) - Generate content from template
  • enableDebug(enable) - Toggle debug mode for troubleshooting

📖 Complete API Documentation → (includes browser/Vite examples)

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please read the contributing guidelines and submit pull requests for any improvements.


SIGIL: Where symbols become worlds