A simple Data Table Editor that generates Markdown, CSV or JSON. It can also be used to interchange data between the formats, supporting editing in the grid.
- Grid interface
- drag and drop rows to re-order
- drag and drop columns to re-order
- import csv from file
- import csv, markdown, and json from editor
- generate csv, markdown, json and javascript from grid
- export csv, markdown and json files
- add and delete columns
- add and delete rows
- randomly fill data with Test Data
- configure export options
The application is live at AnyWayData.com
- Or clone and run locally by opening index.html in a browser after starting a web server in the folder e.g.
python3 -m http.server
The editor can run with AG Grid or Tabulator using the same import/export and toolbar processing layer.
- Query string:
?grid=ag-gridor?grid=tabulator - Global override before app load:
window.ANYWAYDATA_GRID_ENGINE = "ag-grid" - Persisted setting key:
localStorage["anywaydata:grid-engine"]
Default is Tabulator.
Use the Generator to create test data rules using a nicer UI.
You can preview the data prior to generating.
You can copy the schema into the editor UI and use it to populate existing tables.
You can add data to an existing data table e.g. you import a CSV file and want to a new column of dates, or you want to amend an entire column (perhaps to obfuscate PII Data)
Expand the "> Test Data" section.
Choose the Data fields to add or amend in the table or enter a spec.
You can then create a new table, or amend the existing table or selected rows.
The spec is a paragraph of text where each line is either a 'name' or a 'rule':
name
rule
name
rule
namewill be used as a column namerulewill be used to generate the data
A rule can be a regex string e.g.
(connie|bob)which would generate 'connie' or 'bob'[1-9][0-9]{0,4}which would generate number between 1 and 99999
A rule can also be a faker API call.
Faker API can be found here: https://fakerjs.dev/api/
e.g.
faker.person.firstNamefaker.hacker.noun
The faker prefix is optional:
e.g.
person.firstNamehacker.noun
The fake method is also supported, which takes a mustache template style string combining api methods e.g.
helpers.fake("{{name.lastName}}, {{name.firstName}}")
So a sample test data spec might look like:
name
helpers.fake("{{name.lastName}}, {{name.firstName}}")
desc
faker.lorem.paragraph
collects
hacker.noun
prefers
(Connie|Bob)
Looking for similar apps to compare features sets and functionality?
There is a maintained list in the documentation:
- Faker.js for domain api
- RandExp.js for regular expression based random data generation
- Tabulator for light weight tables
- PapaParse for csv processing
This tool falls in to the categories:
- online markdown editor
- markdown table generator
- markdown table editor
- Online Test Data Generation
- Online CSV Editor
Test - npm test
Coverage - npm run testcoverage
Preview Docs - npm run previewdocs
Build for release - npm run anywaydata:win
This repository now uses npm workspaces:
packages/core-> shared generation engine (@anywaydata/core)packages/core-ui-> browser UI modules (@anywaydata/core-ui)packages/cli-> CLI wrapper (@anywaydata/cli)apps/api-> REST API (@anywaydata/api)apps/mcp-> MCP server (@anywaydata/mcp)
Imports now resolve directly from package sources.
Use packages/core/js/* and packages/core-ui/js/* paths in local runtime/test code.
Install all dependencies from the repo root:
npm install
Run workspace build/test orchestration from root:
npm run build:workspacesnpm run test:workspaces
Run an individual workspace command:
npm run test --workspace @anywaydata/corenpm run test --workspace @anywaydata/core-uinpm run start --workspace @anywaydata/apinpm run start --workspace @anywaydata/mcp
The npm CLI package is the workspace package @anywaydata/cli (separate from the Bun CLI in cli/).
Install globally from npm:
npm install -g @anywaydata/cli
Or run without installing:
npx @anywaydata/cli --help
Run a one-off generation command with npx:
npx @anywaydata/cli generate -i input.txt -n 10 -f csv
Show CLI help:
anywaydata --help
Generate output to console:
anywaydata generate -i input.txt -n 10 -f csv
Generate output to a file:
anywaydata generate -i input.txt -n 10 -f json -o output.json
Run in test mode (forces a single generated row and prints diagnostics):
anywaydata generate -i input.txt -n 10 -f markdown -t
Supported options:
-i, --inputfilepath to the input text spec (required)-n, --numberOfLinesnumber of rows to generate (default1)-f, --formatoutput format (defaultcsv)-o, --outputfilewrite output to file instead of stdout-t, --testModeenable diagnostics mode and generate one row--unsafe-faker-expressionsallow expression-style faker args (disabled by default)
Start the API:
npm run start --workspace @anywaydata/api
Run the published API package directly with npx:
npx -y @anywaydata/api
Or run it by binary name:
npx -y anywaydata-api
For interactive local development (foreground process with Ctrl+C stop), prefer:
npm run start --workspace @anywaydata/api -- --port 3001node apps/api/src/index.js --port 3001
Use npx primarily for consumer-style package execution/testing.
Choose a specific port:
npm run start --workspace @anywaydata/api -- --port 3001- PowerShell:
$env:PORT=3001; npm run start --workspace @anywaydata/api
Port behavior:
--portoverridesPORT- if a port is explicitly provided (
--portorPORT) and is in use, startup fails with a short message - if no explicit port is provided, API starts at
3000and auto-tries3001..3020when needed
Health check:
GET http://localhost:3000/health
Generate data:
POST http://localhost:3000/v1/generate
/v1/generate request supports optional responseFormat mode:
responseFormat: "rows"(default) returnsheaders+rowsresponseFormat: "rendered"returns only rendered text in JSON payloadresponseFormat: "all"returnsheaders+rows+renderedresponseFormat: "raw"returns rendered payload directly with content-type matching output formatoutputFormatis optional and defaults tocsvoutputFormatsupports:csv,dsv,markdown,json,jsonl,javascript,python,java,typescript,xml,sql,gherkin,html,asciitable
Raw multiline schema/spec endpoint:
POST http://localhost:3000/v1/generate/fromschema?rowCount=10&outputFormat=csv&responseFormat=rows
Content-Typemust betext/plain- request body is the full multiline spec
- query params:
rowCount(required),outputFormat(optional),seed(optional),responseFormat(optional:rows|rendered|all|raw)
Set format default options:
POST http://localhost:3000/v1/generate/options/<format>
Get current format default options:
GET http://localhost:3000/v1/generate/options/<format>
Reset format default options:
POST http://localhost:3000/v1/generate/options/<format>/default
Notes:
- option defaults set for a format are used when
optionsare not provided to/v1/generateor/v1/generate/fromschema - payload for
/v1/generate/options/<format>is the same options object normally sent asoptionsin generation requests
Notes:
- for JSON requests, newline characters inside string literals must be escaped as
\\n - use
/v1/generate/fromschemawhen you want to paste raw multiline text directly
OpenAPI spec:
GET http://localhost:3000/openapi.json
Swagger UI:
GET http://localhost:3000/docs
Example request body:
{
"textSpec": "Name\nBob",
"rowCount": 3,
"outputFormat": "json"
}Start the MCP server:
npm run start --workspace @anywaydata/mcp
Note: MCP runs over stdio in this version and does not bind to a TCP port. OpenAPI/Swagger routes are available on the REST API only.
The server exposes tools:
generate_data_from_specget_output_format_options_schema
Inputs:
textSpec(required string)rowCount(required integer, >= 0)outputFormat(required string e.g.csv,json,jsonl,xml,sql)options(optional object)seed(optional number)
Discoverability support:
tools/listpublishes typedinputSchemaandoutputSchemaget_output_format_options_schemareturns per-format defaults and typed option schemaresources/listandresources/readexpose:anywaydata://schemas/output-format-optionsanywaydata://install/config-examples
Security note:
- MCP input validation restricts faker rule arguments to literals only (string/number/boolean/null) or no args.
- Expression-style faker arguments (e.g. arrow functions,
this, template expressions) are rejected in MCP mode. - Node and Bun CLIs are also safe-by-default with the same rule; use
--unsafe-faker-expressionsto opt in.
Error conventions:
- Tool-level validation/safety failures return
result.isError=true - Tool payload shape for failures is:
{ "ok": false, "error": { "code": "...", "message": "...", "details": ... } }
- Common
error.codevalues:invalid_output_formatunsafe_faker_ruletext_spec_too_largerow_count_too_largegeneration_failed
Codex connects to this server as an MCP tool provider over stdio (not HTTP).
- Ensure dependencies are installed from repo root:
npm install
- Start MCP server (or let your MCP host launch it):
npm run start --workspace @anywaydata/mcp
- Configure your MCP host/Codex to launch the server command.
Example MCP server config (published package via npx):
{
"mcpServers": {
"anywaydata": {
"command": "npx",
"args": ["-y", "@anywaydata/mcp"]
}
}
}Example MCP server config (Claude Desktop style):
{
"mcpServers": {
"anywaydata": {
"command": "npx",
"args": ["-y", "@anywaydata/mcp"]
}
}
}Example MCP server config (Cursor/Cline-style local repo command):
{
"mcpServers": {
"anywaydata-local": {
"command": "node",
"args": ["apps/mcp/src/index.js"],
"cwd": "D:/github/grid-table-editor"
}
}
}Windows-safe alternative (avoids npx bin resolution issues in some shells):
{
"mcpServers": {
"anywaydata": {
"command": "node",
"args": ["-e", "import('@anywaydata/mcp')"]
}
}
}Example MCP server config (local repo):
{
"mcpServers": {
"anywaydata": {
"command": "node",
"args": ["apps/mcp/src/index.js"],
"cwd": "D:/github/grid-table-editor"
}
}
}For MCP hosts, prefer direct node execution or npx as shown above. npm run can emit non-JSON stdout lines, which may interfere with stdio MCP message parsing in some clients.
Notes:
- Transport is
stdio, soPORT/--portdo not apply to MCP. - Use REST API (
@anywaydata/api) for HTTP/OpenAPI/Swagger use cases. - MCP tool name exposed is
generate_data_from_spec.
Packages are configured with publishConfig.access=public.
npm loginnpm installnpm run verify:local
Versioning and release notes are managed with Changesets:
- Create new changeset
npx changeset- Commit the generated changeset file
- Bump version
npx changeset version- publish package
npx changeset publish
For manual one-off publish, set the version in that package’s package.json first, then publish.
Bump version:
npm version patch --workspace @anywaydata/cli
or minor / major / exact like 1.2.3
Publish a single workspace package manually:
npm publish --workspace @anywaydata/corenpm publish --workspace @anywaydata/core-uinpm publish --workspace @anywaydata/cli
Build images from repo root:
docker build -f apps/api/Dockerfile -t anywaydata-api .
Run the API container:
docker run --rm -p 8082:3000 anywaydata-api
Then sent requests to:
localhost:8082
e.g.
GET http://localhost:8082/healthGET http://localhost:8082/v1/generate/options/csv
Notes:
docker run: starts a new container from an image.--rm: automatically removes the container when it stops.-p 8082:3000: maps host port8082to container port3000.anywaydata-api: the image name to run.- Connect from your machine at
http://localhost:8082. - Inside the container, the app still listens on port
3000.
Build the browser app image from repo root:
docker build -f apps/web/Dockerfile -t anywaydata-web .
Run the browser app container:
docker run --rm -p 8080:80 anywaydata-web
Then open:
http://localhost:8080/http://localhost:8080/app.htmlhttp://localhost:8080/generator.html
Notes:
- This image serves the static browser app assets only.
- It does not build or include Docusaurus (
docs-srcpipeline).
Build images from repo root:
docker build -f apps/mcp/Dockerfile -t anywaydata-mcp .
Configure MCP with stdio for Docker
Example MCP config:
{
"mcpServers": {
"anywaydata-docker": {
"command": "docker",
"args": ["run", "--rm", "-i", "anywaydata-mcp"]
}
}
}Notes:
- Build first:
docker build -f apps/mcp/Dockerfile -t anywaydata-mcp .` -iis required for stdio transport.- No
-pmapping is needed for MCP.
If you need local files available inside the container, add a bind mount, e.g. -v /host/path:/workspace.
Start both services with Compose:
docker compose up --build
GitHub Actions runs linting and tests for pushes and pull requests to master.
The workflow also publishes coverage output as build artifacts on each run:
coverage-report-node-20.xcontains the fullcoverage/directorycoverage-html-report-node-20.xcontains the HTML report fromcoverage/lcov-report/
Open the workflow run in the Actions tab and download the artifact from the run summary page.
- TODO: convert all JS to TypeScript
- TODO: improve and expand the test data generation - written in TypeScript, don't use faker directly - create a full semantic abstraction
- TODO: create a DSL for the test data generation... probably just JSON initially
- TODO: convert UI to use React?
Large sources of data: