Skip to content

CLI Reference

Ashley Towner edited this page Sep 6, 2025 · 1 revision

Shadowdark Parser CLI

A command-line tool for parsing Shadowdark RPG content from plaintext files or stdin into JSON or custom formatted output using Handlebars templates.

Installation

Global Installation

npm install -g shadowdark-parser

Using npx (Recommended)

npx shadowdark-parser [options] [filename]

Basic Usage

Parse a file to JSON

# Parse a file and output JSON to stdout
npx shadowdark-parser monster.txt

# Parse from stdin
cat monster.txt | npx shadowdark-parser
# or
npx shadowdark-parser -

Save output to a file

npx shadowdark-parser monster.txt -o output.json

Command-Line Options

Usage: shadowdark-parser [options] [filename]

Arguments:
  filename               The filename to parse. If set to - or left blank, will
                         read from stdin (default: "-")

Options:
  -t, --template <file>  A handlebars template file
  -o, --output <file>    The file to output to
  -b, --bulk             Mark the input as containing multiple entities, one
                         after the other
  -n, --name-from-file   Use the name of the file as the name of the entity.
                         This option will do nothing if the file is stdin
  -h, --help             display help for command

Examples

Basic File Parsing

Input file (stingbat.txt):

STINGBAT
Darting, orange insect-bat with four wings and needlelike beak.
AC 12, HP 4, ATK 1 beak +2 (1d4 + blood drain), MV near (fly), 
S -2, D +2, C +0, I -2, W +0, Ch -2, AL N, LV 1
Blood Drain. Attach to bitten target; auto-hit the next round.
DC 9 STR on turn to remove.

Command:

npx shadowdark-parser stingbat.txt

Output:

{
  "type": "monster",
  "name": "STINGBAT",
  "description": "Darting, orange insect-bat with four wings and needlelike beak.",
  "ac": 12,
  "hp": 4,
  "attacks": [[{
    "type": "attack",
    "quantity": "1",
    "name": "beak",
    "bonus": "+2",
    "damage": "1d4 + blood drain"
  }]],
  "movementDistance": "near",
  "movementType": "fly",
  "strength": -2,
  "dexterity": 2,
  "constitution": 0,
  "intelligence": -2,
  "wisdom": 0,
  "charisma": -2,
  "alignment": "Neutral",
  "level": 1,
  "traits": [{
    "type": "trait",
    "name": "Blood Drain",
    "description": "Attach to bitten target; auto-hit the next round. DC 9 STR on turn to remove."
  }]
}

Using Handlebars Templates

Create a template file to format the output in any way you want.

Template file (monster.hbs):

# {{name}}
{{#if description}}*{{description}}*{{/if}}

**AC** {{ac}}{{#if armor}} ({{armor}}){{/if}}, **HP** {{hp}}, **ATK** {{#each attacks}}{{#each this}}{{#if quantity}}{{quantity}} {{/if}}{{name}}{{#if range}} ({{range}}){{/if}} {{bonus}}{{#if damage}} ({{damage}}){{/if}}{{#unless @last}} and {{/unless}}{{/each}}{{#unless @last}} or {{/unless}}{{/each}}, **MV** {{movementDistance}}{{#if movementType}} ({{movementType}}){{/if}}, **S** {{signedNumber strength}}, **D** {{signedNumber dexterity}}, **C** {{signedNumber constitution}}, **I** {{signedNumber intelligence}}, **W** {{signedNumber wisdom}}, **Ch** {{signedNumber charisma}}, **AL** {{firstChar alignment}}, **LV** {{level}}

{{#each traits}}
**{{name}}.** {{description}}

{{/each}}

Command:

npx shadowdark-parser stingbat.txt -t monster.hbs

Output:

# STINGBAT
*Darting, orange insect-bat with four wings and needlelike beak.*

**AC** 12, **HP** 4, **ATK** 1 beak +2 (1d4 + blood drain), **MV** near (fly), **S** -2, **D** +2, **C** +0, **I** -2, **W** +0, **Ch** -2, **AL** N, **LV** 1

**Blood Drain.** Attach to bitten target; auto-hit the next round. DC 9 STR on turn to remove.

Bulk Parsing Multiple Entities

When you have multiple entities in a single file, use the -b flag:

Input file (monsters.txt):

SPIDER
A web-spinning arachnid.
AC 13, HP 9, ATK 1 bite +3 (1d4 + poison), MV near (climb), 
S -1, D +3, C +0, I -3, W +1, Ch -3, AL N, LV 2
Poison. DC 12 CON or paralyzed 1d4 rounds.

STINGBAT
Darting, orange insect-bat with four wings.
AC 12, HP 4, ATK 1 beak +2 (1d4), MV near (fly), 
S -2, D +2, C +0, I -2, W +0, Ch -2, AL N, LV 1

Command:

npx shadowdark-parser monsters.txt -b

This will output an array of parsed entities instead of a single entity.

Using File Name as Entity Name

For entities that don't have a clear name in the text, use the -n flag to use the filename:

Command:

npx shadowdark-parser "Fire Elemental.txt" -n

This will treat "Fire Elemental" as the entity's name.

Complex Pipeline Example

# Parse multiple monsters, format with template, save to markdown file
npx shadowdark-parser monsters.txt -b -t monster.hbs -o formatted_monsters.md

Handlebars Templates

The CLI uses Handlebars for templating. You have access to all standard Handlebars features plus custom helpers.

Custom Helpers

signedNumber

Ensures numbers always display with a + or - sign.

Strength: {{signedNumber strength}}
<!-- Output: Strength: +3 or Strength: -2 -->

firstChar

Returns the first character of a string.

Alignment: {{firstChar alignment}}
<!-- Output: Alignment: N (for Neutral) -->

eq

Tests equality between two values.

{{#if (eq type "monster")}}
This is a monster!
{{/if}}

Template Context

The template receives the parsed entity data as context. For bulk parsing, it receives an array of entities.

Single entity context:

{
  "type": "monster",
  "name": "STINGBAT",
  "ac": 12,
  // ... other properties
}

Bulk parsing context (array):

[
  {"type": "monster", "name": "SPIDER", ...},
  {"type": "monster", "name": "STINGBAT", ...}
]

Template Examples

Simple Monster Card

**{{name}}** (Level {{level}})
AC {{ac}}, HP {{hp}}
{{description}}

Spell List

{{#each this}}
### {{name}}
*Tier {{tier}}, {{classes}}*
- **Duration:** {{duration}}
- **Range:** {{range}}

{{description}}

{{/each}}

Roll Table

# {{name}}

| Roll | Result |
|------|--------|
{{#each results}}
| {{range.[0]}}{{#unless (eq range.[0] range.[1])}}-{{range.[1]}}{{/unless}} | {{text}} |
{{/each}}

Supported Entity Types

The CLI automatically detects and parses:

  • Monsters: Creatures with stat blocks (AC, HP, ATK, etc.)
  • Spells: Magic with tier, duration, range, and description
  • Magic Items: Items with benefits, curses, and other traits
  • Roll Tables: Numbered lists for random generation

Error Handling

If parsing fails, the CLI will output an error message and exit with code 1:

npx shadowdark-parser invalid.txt
# Error: Could not parse stats from statblock...

Integration Examples

With other CLI tools

# Parse and pretty-print JSON
npx shadowdark-parser monster.txt | jq

# Convert to YAML
npx shadowdark-parser monster.txt | yq -P

# Search for specific monsters
npx shadowdark-parser monsters.txt -b | jq '.[] | select(.level > 5)'

In shell scripts

#!/bin/bash
# Convert all .txt files in a directory
for file in *.txt; do
    npx shadowdark-parser "$file" -n -o "${file%.txt}.json"
done

With build systems

# In package.json scripts
{
  "scripts": {
    "parse-monsters": "npx shadowdark-parser data/monsters.txt -b -o dist/monsters.json",
    "build-compendium": "npx shadowdark-parser src/*.txt -b -t templates/compendium.hbs -o dist/compendium.html"
  }
}