Realistic test data. One command.

Names that match their emails, cities that exist, order amounts with a real long tail, foreign keys that actually join. rgen runs on an embedded DuckDB engine and writes CSV, JSON, Parquet, Excel, DuckDB or SQLite. No Python environment, no Faker scripts.

curl -fsSL https://cuiqanalytics.github.io/rgen/install.sh | sh

Free, with no row limits. No account, no telemetry.

Every bead takes a random path. Together they land in a bell curve. That's the idea behind rgen: random values, realistic shape.

From docker pull to a cloned dataset in 52 seconds

Every command and every row in this video is real rgen output.

One line in. A table out.

List the columns you want, separated by semicolons. Rename them with as. Let later columns build on earlier ones: here the email is made from the generated name, so the rows hold together when someone reads them.

Pick the format with the file extension. .parquet, .json and .xlsx work the same way.

Prefer clicking? The editor builds the same command for you.

$ rgen run -n 1000 -p "first_name;last_name;
  email_from_name(first_name,last_name) as email;
  city;company as employer" customers.csv
✓ 1000 records in 86ms (102 KB)
first_namelast_nameemailcityemployer
BrianTaylorbrian.taylor@example.comVyazemskiyTitan Solutions
PaulHarrispaul.harris@example.comKavajëQuantum Solutions
RonaldPhillipsronald.phillips@example.comPhalodiPinnacle Dynamics
HannahParkerhannah.parker@example.comTuttlingenSpectrum Ventures
RichardMillerrichard.miller@example.comKovancılarPinnacle Industries

Prefer clicking? Use the editor

Run rgen ui and the editor opens in your browser. Pick columns from the list, rename them, check ten sample rows, then save the file as CSV, JSON, Parquet or Excel. It also shows the matching rgen run command, ready to paste into a script.

rgen ui
The rgen editor: a list of column types on the left, ten sample rows of a customers table in the middle, and file options with the matching rgen run command on the right
Runs on your machine and listens only on localhost. No account, no upload.

101 providers, with values that look right

Each sample below came out of rgen. Filter by name, category or what you need.

ProviderCategorySample values

Clean data hides bugs

Real data has nulls, shouting capitals, half-typed names, broken emails, negative amounts and dates in the wrong format. Add --impurity-profile and rgen breaks a share of the cells the way real systems do, so your pipeline meets those problems in testing.

  1. clean0%
  2. realistic3%
  3. noisy10%
  4. dirty25%
  5. chaotic50%
$ rgen run -n 400 --impurity-profile dirty \
  -p "first_name;email;date(...) as signup;amount(10,500) as amount" signups.csv
first_nameemailsignupamount
Dorothymark.murphy56@example.com.fake.com2024-05-2524
Carolmatthew.williams14@example.com2024-02-16-367
Jessicapatricia.thompson75@example.com11/08/2024-250
NULLdorothy.carter71@example.com2024-10-1427
Kimberlymartha.collins742024-07-09-493
Michelleandrew.davis66example.com2024-01-24167
Baredward.brown62@example.com2024-04-08318
LISANULL2024-12-1382

Tables that reference each other

Describe a schema in TOML: foreign keys, category mixes, skewed amounts, computed columns. rgen builds parents before children, so every reference points at a row that exists.

[[tables]]
name = "customers"
rows = 2000
    [tables.columns]
    customer_id = { provider = "uuid", primary_key = true }
    name        = { provider = "name" }
    country     = { provider = "choice",
                    distribution = "weighted",
                    params = { values = ["US", "UK", "DE", "MX"],
                               weights = [0.5, 0.2, 0.2, 0.1] } }

[[tables]]
name = "orders"
rows = 20000
    [tables.columns]
    order_id    = { provider = "uuid", primary_key = true }
    customer_id = { provider = "choice",
                    reference = "customers.customer_id" }
    ordered_at  = { provider = "date",
                    params = { from = "2025-01-01", to = "2025-12-31" } }
    amount      = { provider = "amount",
                    distribution = "lognormal",
                    params = { min = 5, max = 2000,
                               median = 60, std_dev = 40 } }
customers 2,000 rows customer_id orders 20,000 rows customer_id 1 to many
$ rgen run --config shop.toml shop.duckdb
  ✓ customers: 2000 rows
  ✓ orders: 20000 rows
$ duckdb shop.duckdb -c "
    SELECT c.country, count(*) AS orders,
           round(avg(o.amount), 2) AS avg_amount
    FROM orders o JOIN customers c USING (customer_id)
    GROUP BY ALL ORDER BY orders DESC"
countryordersavg_amount
US10,40270.82
UK4,11371.49
DE3,70572.41
MX1,78070.73

Every one of the 20,000 orders joins to a customer, and the 50/20/20/10 country mix carries through.

Time series

Entities × time buckets. 50 sensors reporting hourly for June is 34,850 rows, with temperatures that drift as a random walk instead of jumping around.

mode = "timeseries"

Lifecycles

Simulate accounts moving between states, with probabilities and delays you set. Out comes an event log:

mode = "state_machine"

Your own data

Attach an existing DuckDB, SQLite, CSV or Parquet file and draw values from it, matched by key or picked at random.

[[attach]]

A twin of your real data, without the real data

Point rgen twin at a CSV, Parquet, SQLite or DuckDB file. It profiles each column (distribution shape, category mix, date range, ID pattern) and generates a fresh dataset with the same shape. Share it with contractors, put it in CI, demo with it. Not a single real row comes along.

Want to adjust the result first? rgen profile sales.csv prints the config it inferred.

$ rgen twin --scale 2.0 sales.csv twin.duckdb
Profiling sales.csv...
Generating synthetic twin → twin.duckdb
  ✓ data: 10000 rows
Revenue per order, share of rows in each $20 bucket
sales.csv (real, 5,000 rows) twin.duckdb (10,000 rows)

Or just ask Claude

rgen ships with a Claude Code skill. It knows the provider list, when to use a one-liner and when a TOML config, how foreign keys and distributions are written, and the mistakes to avoid. It checks its work by running rgen before it hands you the result.

~/.local/lib/rgen/install-skills.sh

Seed my dev database with 500 customers, their orders and order items. Most orders should be small, a few huge.

I'll write seed.toml with three linked tables: order_items references orders, orders reference customers, and amounts follow a lognormal so most are small with a long tail. Then I'll run rgen run --config seed.toml dev.duckdb and check the joins before handing it over.

Start with a recipe

Copy one, run it, then change it. Every command works on the free CLI.

A users table for a seed script

Names, matching emails and real cities. Change -n for more rows.

rgen run -n 1000 -p "uuid;first_name;last_name;email;city;country" users.csv

Look before you write

Print a few rows to the terminal instead of a file while you pick columns.

rgen run --preview -p "name;email;phone;company"

Customers, products and orders that join

A built-in template with foreign keys. Edit the TOML to add columns or change row counts.

rgen templates orders > orders.toml && rgen run --config orders.toml shop.duckdb

Messy data for QA

Blanks, typos and malformed values in about a quarter of the cells, to test validation and cleaning code.

rgen run -n 5000 --impurity-profile dirty -p "uuid;email;first_name;city" dirty.csv

Sensor readings over time

50 sensors with hourly random-walk temperatures, from the examples folder.

curl -fsSLO https://raw.githubusercontent.com/cuiqanalytics/rgen/main/examples/sensors.toml && rgen run --config sensors.toml readings.duckdb

A safe copy of a real dataset

Profile a CSV, Parquet, SQLite or DuckDB file and generate synthetic rows with the same shape.

rgen twin --scale 2.0 sales.csv twin.duckdb

More in the quick reference and the examples folder. rgen templates lists the built-in configs.

Data packs

Packs add curated reference data, new providers and ready-made templates on top of the free CLI. Every pack is checked with automated tests, and identifiers are verified with independent validators.

How packs work

  1. Email us the pack you want. We reply with a license key and the pack file.
  2. Install both:
    rgen license install <KEY> && rgen packs install ./fintech.rgenpack
  3. Use it: the pack's providers show up in rgen providers, and its configs in rgen templates.
    rgen templates fintech/card-transactions > cards.toml && rgen run --config cards.toml cards.duckdb

Licenses are checked offline. If one lapses, the pack stops loading; the free CLI and everything you already generated stay yours.

The tool is free. Data packs are extra.

rgen

$0

  • All 101 providers, locales and dependent columns
  • Any number of rows: CSV, JSON, Parquet, Excel, DuckDB, SQLite
  • Relational configs with foreign keys
  • Time series, lifecycles and scenarios
  • rgen profile and rgen twin digital twins
  • rgen ui, a visual editor in your browser
  • Impurity profiles, your own DuckDB macros, the Claude Code skill
Install rgen

Single pack

$79 per year

  • One data pack of your choice
  • Its providers, lookup tables and templates
  • Updates to that pack for the year
  • Works offline, on any machine you use
Buy a pack

All packs

$199 per year

  • Every current pack: fintech, latam, hr, saas-analytics, weather, healthcare, security-logs, insurance, logistics, retail, telecom, energy, education, travel, jobs-pro
  • New packs as they ship, at no extra cost
  • Updates for the year
  • Works offline, on any machine you use
Get all packs

Teams, on-prem use or invoicing: write to us.

Questions

Is any of the generated data real?

No. Every row is generated. Reference lists such as city names, occupations, merchant categories and wage statistics come from public datasets, but the people, accounts and IDs are random. A generated ID can still match a real one by chance, so never use it to contact, verify or charge anyone.

Can I use the data commercially?

Yes. The data you generate is yours: put it in demos, tests, docs or products. rgen packs info <pack> lists the public sources inside each pack and their licenses.

Does rgen need internet access or an account?

No. It's a single binary that runs offline, and pack licenses are verified offline too. No telemetry.

Is there a graphical interface?

Yes. rgen ui opens an editor in your browser: search the providers, add and reorder columns, preview rows, then save the file. It runs on your machine, listens only on localhost and needs no internet. --port changes the port (default 7842).

Does it run on macOS and Windows?

The native binary is for Linux (x86-64). On macOS and Windows, use the Docker image: docker pull ghcr.io/cuiqanalytics/rgen.

Are the IDs and bank numbers valid?

Pack identifiers pass the same checks real systems use: Luhn for cards, IBAN mod-97 with national check digits, US routing numbers, CLABE, and the check digits of RUT, CUIT, CURP, RFC, CPF, CNPJ, NIT, RUC and CI. We test them against python-stdnum and schwifty on every pack build.

What happens when a pack license expires?

That pack stops loading. Everything else keeps working, and data you already generated is unaffected.

How do I buy a pack?

Email rodrigo.abt@gmail.com with the pack you want. You'll get a license key and the pack file, usually within a business day. Card checkout is coming.

Can I get a refund, a team license or an invoice?

Yes. Write to us and we'll sort it out.

Can an AI assistant use rgen?

Yes. Install the Claude Code skill and ask for the data you need; Claude picks the providers or writes the TOML config and runs rgen for you.