CLI Tool
The @morphql/cli tool allows you to perform structural data transformations directly from your terminal. It supports single-file transformations, batch processing of directories, and real-time file monitoring via a watch mode.
Installation
Install it globally to use the morphql command anywhere:
npm install -g @morphql/cliOr run it via npx without installation:
npx @morphql/cli --helpSingle-File Mode
The default mode transforms a single input. Pass a query and provide input via file, string, or stdin pipe.
morphql -i '{"hello": "world"}' -q "from json to xml"Options
| Option | Alias | Description |
|---|---|---|
--query | -q | The MorphQL query string to execute. |
--query-file | -Q | Path to a file containing the MorphQL query. |
--from | -f | Path to the source file. |
--input | -i | Raw source content as a string. |
--to | -t | Path to the destination file. |
--cache-dir | Directory for compiled query cache (default: .compiled). | |
--log-format | Log output format: text (default) or json. |
Note: If
--tois omitted, the result is printed tostdout. All logs/errors go tostderr.
Examples
File-to-File:
morphql \
--from ./input.json \
--to ./output.xml \
-q "from json to xml transform set fullName = firstName + ' ' + lastName"Using a query file:
morphql --from ./input.json --to ./output.xml -Q ./queries/transform.mqlPiping:
cat data.json | morphql -q "from json to json transform set id = uuid"
morphql --from data.json -q "from json to json" | jq .Batch Mode
The batch subcommand processes all files in a directory with a single command. This replaces the need for manual shell loops.
morphql batch \
-q "from xml to json" \
--in ./invoices/ \
--out ./converted/Options
| Option | Description |
|---|---|
-q, --query <string> | MorphQL query string (*). |
-Q, --query-file <path> | Path to a file containing the query (*). |
--in <path> | (Required) Input directory. |
--out <path> | (Required) Output directory (created if missing). |
--pattern <glob> | Include pattern for filenames (default: *). |
--done-dir <path> | Move source files here after success. |
--error-dir <path> | Move source files here on failure. |
--delete | Delete source files after successful processing. |
--cache-dir <path> | Compiled query cache directory (default: .compiled). |
--log-format <format> | Log output format: text (default) or json. |
(*) Provide either
--queryor--query-file.
Behavior
- Validates that
--inexists and is a directory. - Creates
--out(and--done-dir,--error-dir) if they don't exist. - Compiles the query once and caches it.
- Lists files matching
--pattern(dot-files are skipped by default). - Transforms each file and writes the result to
--outwith the correct extension. - Prints a summary with file count, errors, and elapsed time.
- If
--deleteis used (and no--done-diris provided), source files are removed after success. - Exits with code
1if any errors occurred,0otherwise.
Examples
Convert only XML files:
morphql batch \
-q "from xml to json" \
--in ./data/ \
--out ./output/ \
--pattern "*.xml"Archive processed files, quarantine failures:
morphql batch \
-q "from csv to json transform set imported = true" \
--in ./spool/inbox/ \
--out ./spool/processed/ \
--done-dir ./spool/archive/ \
--error-dir ./spool/failed/ \
--pattern "*.csv"
**Delete source files after transformation:**
```bash
morphql batch -q "from json to xml" --in ./in --out ./out --delete
---
## Watch Mode
The `watch` subcommand monitors a directory and automatically transforms files as they appear. It is event-driven (uses `fs.watch`) and designed for long-running processes.
```bash
morphql watch \
-q "from xml to json" \
--in ./incoming/ \
--out ./processed/ \
--pattern "*.xml"Options
Same as Batch Mode, plus:
| Option | Description |
|---|---|
--pid-file <path> | Write the process PID to a file (for process management). |
Behavior
- On startup, performs an initial sweep of all existing files in
--in. - Then watches for new files using an event-driven mechanism.
- File writes are debounced (100ms) to handle multi-step writes safely.
- Dot-files (e.g.,
.temp.json) are ignored by default. - Handles
SIGTERMandSIGINTfor graceful shutdown. - If
--pid-fileis specified, writes the PID on start and cleans up on exit.
Examples
Monitor and log in JSON:
morphql watch \
-q "from csv to json" \
--in ./incoming \
--out ./processed \
--pattern "*.csv" \
--log-format jsonWith PID file (for use with flock):
morphql watch \
-q "from xml to json" \
--in ./spool/in \
--out ./spool/out \
--pid-file /var/run/morphql.pidStructured Logging
Both batch and watch modes support structured logging via --log-format.
Text (Default)
Human-readable output with timestamps:
[23:09:01] INFO: Transformed order.xml → order.json (12ms)
[23:09:01] ERROR: bad.xml — Lexing errors: unexpected character
[23:09:01] INFO: Summary: 3 files processed, 1 error in 380msJSON
One JSON object per line (JSONL), ideal for log aggregation and monitoring:
{"ts":"2026-02-11T23:09:01.123Z","level":"info","msg":"Transformed","input":"order.xml","output":"order.json","duration":12}
{"ts":"2026-02-11T23:09:01.124Z","level":"error","msg":"Lexing errors","input":"bad.xml"}
{"ts":"2026-02-11T23:09:01.130Z","level":"info","msg":"Summary","processed":3,"errors":1,"duration":380}Redirect JSON logs to a file:
morphql batch -q "from json to json" --in ./data --out ./out --log-format json 2> batch.logRunning as a Linux Service
The watch mode is designed to run as a system service. It handles SIGTERM for graceful shutdown and supports PID files for process management.
Systemd Unit File
Create /etc/systemd/system/morphql-watcher.service:
[Unit]
Description=MorphQL Directory Watcher
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/html/project
ExecStart=/usr/bin/node node_modules/.bin/morphql watch \
-q "from xml to json transform set status = 'imported'" \
--in ./spool/in \
--out ./spool/out \
--pattern "*.xml" \
--pid-file /run/morphql.pid \
--log-format json
Restart=always
StandardError=journal
StandardOutput=null
[Install]
WantedBy=multi-user.targetThen enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable morphql-watcher
sudo systemctl start morphql-watcherView logs via journalctl:
journalctl -u morphql-watcher -fUsing with flock
For lightweight process locking without systemd (e.g., triggered by cron):
flock -n /tmp/morphql.lock morphql watch \
-q "from xml to json" \
--in ./spool/in \
--out ./spool/out \
--pid-file /tmp/morphql.pidCaching
The CLI automatically caches compiled queries in a .compiled directory (or a custom path via --cache-dir). This significantly speeds up subsequent executions of the same query by skipping the compilation step. Caching works across all modes (single-file, batch, and watch).
