Running a query from the CLI and outputting it as a .ndjson file in Sanity.io
Unfortunately, sanity documents query outputs standard JSON (an array), not NDJSON format. However, you can easily work around this to achieve your goal of querying from one dataset and importing to another.
The Problem
The sanity documents query command outputs JSON as an array of results, while sanity dataset import requires NDJSON (newline-delimited JSON where each document is on its own line).
Solutions
Option 1: Use jq to Convert JSON to NDJSON (Recommended)
You can pipe the query output through jq to convert it to NDJSON format:
pnpm -F studio exec sanity documents query \
--dataset archive \
'*[_type == "event"]{..., "tags": [], "fromArchive": true}' \
| jq -c '.[]' > ./apps/studio/exports/archived-events.ndjsonThe jq -c '.[]' command:
.[]iterates over each element in the JSON array-coutputs compact JSON (one line per document)
Then import it to your target dataset:
pnpm -F studio exec sanity dataset import \
./apps/studio/exports/archived-events.ndjson \
productionOption 2: Use sanity dataset export with Post-Processing
If your filtering needs are complex, you could export the entire dataset and then filter:
# Export the archive dataset
sanity dataset export archive archive-export.tar.gz
# Extract, filter the NDJSON, then import
sanity dataset import filtered-events.ndjson productionThis approach works well when you need to transform documents beyond what GROQ queries can do.
Option 3: Use a Custom Script with sanity exec
For maximum control, create a migration script using sanity exec:
// scripts/migrate-from-archive.js
import {getCliClient} from 'sanity/cli'
import {createWriteStream} from 'fs'
const client = getCliClient()
const archiveClient = client.withConfig({dataset: 'archive'})
const query = '*[_type == "event"]{..., "tags": [], "fromArchive": true}'
const docs = await archiveClient.fetch(query)
const writeStream = createWriteStream('./exports/archived-events.ndjson')
docs.forEach(doc => {
writeStream.write(JSON.stringify(doc) + '\n')
})
writeStream.end()Run it with:
sanity exec scripts/migrate-from-archive.js --with-user-tokenRecommended Approach
Use Option 1 with jq - it's the simplest and most direct solution. The jq tool is widely available on most systems (or easily installable via package managers like brew install jq on macOS or apt-get install jq on Ubuntu) and is perfect for this JSON-to-NDJSON conversion task.
The key insight is that sanity documents query returns a JSON array, so you just need to unwrap that array into individual lines - which is exactly what jq -c '.[]' does.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.