gnu-recutils
SKILL.md
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
| Command | Purpose |
|---|---|
recsel |
Select and query records |
recins |
Insert new records |
recdel |
Delete records |
recset |
Modify field values |
recfix |
Validate, check integrity, sort |
recfmt |
Format output with templates |
recinf |
Print information about rec files |
rec2csv |
Convert to CSV |
csv2rec |
Convert 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
| Descriptor | Purpose | Example |
|---|---|---|
%rec: Type |
Names the record type | %rec: Entity |
%key: field |
Primary key (unique, mandatory) | %key: Id |
%mandatory: f1 f2 |
Required fields | %mandatory: Id Name |
%allowed: f1 f2 |
Whitelist of valid fields | %allowed: Id Name Desc |
%prohibit: f1 |
Forbidden fields | %prohibit: Password |
%unique: field |
Field must be unique | %unique: Email |
%type: field type |
Field type constraint | %type: Count int |
%auto: field |
Auto-generated field | %auto: Created_at |
%sort: field |
Default sort order | %sort: Name |
Field Types
| Type | Description | Example Values |
|---|---|---|
int |
Integer | 42, -7 |
real |
Floating point | 3.14, -2.5 |
bool |
Boolean | yes, no, true, false, 1, 0 |
line |
Single line (no newlines) | Hello world |
date |
ISO 8601 date | 2024-01-15 |
email |
Email address | user@example.com |
uuid |
UUID | 550e8400-e29b-41d4-a716-446655440000 |
rec Type |
Foreign key reference | References another record type |
enum A B C |
Enumeration | One of the listed values |
regexp /pattern/ |
Regex pattern | Must match pattern |
size N |
Max size in bytes | String length limit |
range MIN MAX |
Numeric range | range 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:
| Operator | Meaning | Example |
|---|---|---|
= |
Equals | Name = "sword" |
!= |
Not equals | Type != "armor" |
<, >, <=, >= |
Numeric comparison | Count > 5 |
~ |
Regex match | Name ~ "^Iron" |
&& |
Logical AND | Type = "weapon" && Rare = yes |
| ` | ` | |
! |
Logical NOT | ! (Count = 0) |
#field |
Field count (0 if absent) | #Description |
Tips
- Use
recfix --checkbefore 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 -pand 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.
Weekly Installs
16
Repository
frizzle-chan/muddGitHub Stars
3
First Seen
Jan 27, 2026
Security Audits
Installed on
opencode15
codex15
gemini-cli15
continue14
cursor14
antigravity14