gnu-recutils

Work with GNU recutils for plain-text record databases. Use when creating, querying, or validating .rec files, defining record schemas with %rec descriptors, converting between rec/CSV formats, or when the user mentions recutils, recsel, recins, recfmt, or record-oriented data files.

$ Instalar

git clone https://github.com/frizzle-chan/mudd /tmp/mudd && cp -r /tmp/mudd/.claude/skills/gnu-recutils ~/.claude/skills/mudd

// tip: Run this command in your terminal to install the skill


name: gnu-recutils description: Work with GNU recutils for plain-text record databases. Use when creating, querying, or validating .rec files, defining record schemas with %rec descriptors, converting between rec/CSV formats, or when the user mentions recutils, recsel, recins, recfmt, or record-oriented data files.

GNU Recutils

GNU recutils is a set of tools for managing human-readable, plain-text databases. Records are stored in .rec files with a simple field: value syntax.

Quick Reference

Core Commands

CommandPurpose
recselSelect and query records
recinsInsert new records
recdelDelete records
recsetModify field values
recfixValidate, check integrity, sort
recfmtFormat output with templates
recinfPrint information about rec files
rec2csvConvert to CSV
csv2recConvert from CSV

Basic File Format

# Comment line
Field_name: field value
Another_field: another value

Field_name: second record
Another_field: its value

Records are separated by blank lines. Field names are case-sensitive and conventionally capitalized.

Multi-line Values

Use + continuation for multi-line content:

Description: This is the first line
+ and this continues on the second line
+ and a third line too.

Or use backslash at end of line:

Description: This is a long value that \
continues on the next line.

Schema Definitions (%rec Descriptors)

Place schema declarations before records:

%rec: Entity
%key: Id
%mandatory: Id Name
%allowed: Id Name Prototype Description OnLook OnTouch
%type: Prototype rec Entity
%type: Count int
%type: Active bool
%unique: Name

Id: sword
Name: Iron Sword
Count: 1
Active: yes

Common Descriptors

DescriptorPurposeExample
%rec: TypeNames the record type%rec: Entity
%key: fieldPrimary key (unique, mandatory)%key: Id
%mandatory: f1 f2Required fields%mandatory: Id Name
%allowed: f1 f2Whitelist of valid fields%allowed: Id Name Desc
%prohibit: f1Forbidden fields%prohibit: Password
%unique: fieldField must be unique%unique: Email
%type: field typeField type constraint%type: Count int
%auto: fieldAuto-generated field%auto: Created_at
%sort: fieldDefault sort order%sort: Name

Field Types

TypeDescriptionExample Values
intInteger42, -7
realFloating point3.14, -2.5
boolBooleanyes, no, true, false, 1, 0
lineSingle line (no newlines)Hello world
dateISO 8601 date2024-01-15
emailEmail addressuser@example.com
uuidUUID550e8400-e29b-41d4-a716-446655440000
rec TypeForeign key referenceReferences another record type
enum A B CEnumerationOne of the listed values
regexp /pattern/Regex patternMust match pattern
size NMax size in bytesString length limit
range MIN MAXNumeric rangerange 1 100

Foreign Key References

%rec: Room
%key: Id

Id: tavern
Name: The Rusty Tavern

%rec: Entity
%key: Id
%type: Room rec Room

Id: mug
Name: Beer Mug
Room: tavern

Entity Containment (MUDD)

Entities can be nested using a Container field:

%rec: Entity
%key: Id
%type: Prototype rec Entity
%type: Container rec Entity

Id: table
Name: Wooden Table
Prototype: furniture

Id: lamp
Name: Brass Lamp
Prototype: object
Container: table

The lamp is "on" the table. Recfix validates that Container references exist.

Common Operations

Query Records

# All records
recsel data.rec

# Filter by field value
recsel -e 'Name = "sword"' data.rec

# Pattern matching
recsel -e 'Name ~ "Iron"' data.rec

# Numeric comparison
recsel -e 'Count > 5' data.rec

# Multiple conditions
recsel -e 'Type = "weapon" && Count > 0' data.rec

# Select specific fields
recsel -p Id,Name data.rec

# Count matching records
recsel -c -e 'Active = yes' data.rec

# Select by record type
recsel -t Entity data.rec

Insert Records

# Insert from stdin
echo -e "Id: axe\nName: Battle Axe" | recins data.rec

# Insert with field values
recins -f Id -v sword -f Name -v "Iron Sword" data.rec

Modify Records

# Update field value
recset -e 'Id = "sword"' -f Count -s 5 data.rec

# Delete field from record
recset -e 'Id = "sword"' -f Obsolete -d data.rec

Delete Records

# Delete matching records
recdel -e 'Count = 0' data.rec

# Delete by record number
recdel -n 3 data.rec

Validate

# Check file integrity
recfix data.rec

# Check and report all errors
recfix --check data.rec

Convert Formats

# To CSV
rec2csv data.rec > data.csv

# From CSV
csv2rec data.csv > data.rec

Format Output

# Custom output format
recsel data.rec | recfmt '{{Id}}: {{Name}}\n'

# Template-based formatting (recfmt reads from stdin)
recsel data.rec | recfmt -f template.fmt

Expression Syntax

Used with -e flag in recsel, recdel, recset:

OperatorMeaningExample
=EqualsName = "sword"
!=Not equalsType != "armor"
<, >, <=, >=Numeric comparisonCount > 5
~Regex matchName ~ "^Iron"
&&Logical ANDType = "weapon" && Rare = yes
``
!Logical NOT! (Count = 0)
#fieldField count (0 if absent)#Description

Tips

  • Use recfix --check before loading data to catch schema violations
  • Foreign keys (%type: Field rec OtherType) validate references exist
  • Field names start with a letter and contain only [a-zA-Z0-9_]; special fields start with %
  • Empty lines separate records; use + continuation for multi-line values
  • Comments start with # at the beginning of a line
  • For JSON output, pipe through recsel -p and parse with a script

MUDD Naming Convention

In this project, entity fields use PascalCase (e.g., DescriptionShort, OnAttack). This avoids visual noise from underscores. See data/entities.rec for examples.