Advanced
Command Line Interface (CLI)
The Messagevisor CLI is the main authoring and operations surface for a project. It covers project setup, validation, examples, evaluation, building, testing, catalog workflows, CSV exchange, and sets-based promotion flows.
This page is the command reference for the CLI. Use it as the practical map, then follow the related links for deeper model-specific details.
Before you start#
The CLI expects to run inside a Messagevisor project directory or a child directory of one.
Typical invocation:
$ npx messagevisor <command> [options]If your project uses sets, some commands require --set=<name> so Messagevisor knows which definition tree to operate on.
Command options are validated strictly. Unknown flags fail before a command runs, while dashed and camel-cased spellings of declared options remain equivalent. Custom CLI plugins must declare their accepted options through the plugin's options field.
Output modes#
Many commands support one or more of these output styles:
- plain text: optimized for humans in a terminal
--json: machine-readable output--pretty: pretty-print JSON output--verbose: more detail for debugging
When a command supports JSON output, prefer it for scripts and CI checks.
Command failures also use a stable JSON envelope when --json is present. The envelope contains error.code, error.message, and optional error.details, allowing automation to react to errors without parsing terminal prose.
Typical authoring loop#
$ npx messagevisor lint$ npx messagevisor test$ npx messagevisor buildAdd these as needed:
exampleswhen you want to inspect authored examplesevaluatewhen you want to debug a single message, raw string, or segmentcatalogwhen you want a browsable project view
init#
Create a new project starter.
Use this when:
- bootstrapping a new repo
- creating a scratch project to try a workflow
- comparing YAML and JSON project layouts
Examples:
$ npx messagevisor init$ npx messagevisor init --project=json$ npx messagevisor init --project=environmentsNotes:
- run
initfrom an empty project directory for the cleanest setup - if the current directory is not empty,
initprompts for a new child directory name and initializes the starter there - pass
--overwriteto initialize in the current directory anyway; existing conflicting files are skipped, not replaced --projectselects a starter shape- the generated project is only a starting point; you will usually tailor directories, config, and modules right away
Read next:
config#
Print the resolved project configuration.
Use this when:
- confirming which parser is active
- checking resolved directory paths
- verifying sets/modules/export options
Examples:
$ npx messagevisor config$ npx messagevisor config --json --prettyNotes:
- this shows resolved configuration, not just the literal contents of
messagevisor.config.js - it is often the fastest way to confirm whether a path override or module registration is being picked up
Read next:
info#
Show a quick entity-count summary for the current project.
Use this when:
- sanity-checking a project after import or promotion
- getting a quick overview before a review or debugging session
Example:
$ npx messagevisor infoRead next:
lint#
Validate project definitions.
Use this when:
- checking schema correctness
- catching missing references and invalid format shapes
- validating tests before running them
Examples:
$ npx messagevisor lint$ npx messagevisor lint --json --pretty$ npx messagevisor lint --set=stagingBehavior notes:
lintvalidates authoring definitions, not runtime output- for sets-based projects,
lintcan cover all sets or a single set depending on how you invoke it - if you are changing locale format presets, target filters, or test assertion shapes,
lintis usually the first command that tells you whether the structure is valid
Read next:
list#
List one class of entity or inspect generated datafiles.
Supported entity switches:
--messages--locales--segments--attributes--targets--tests--datafiles
Examples:
$ npx messagevisor list --messages$ npx messagevisor list --messages --target=web$ npx messagevisor list --locales$ npx messagevisor list --targets$ npx messagevisor list --datafiles$ npx messagevisor list --datafiles --json --prettylist --datafiles shows generated paths relative to datafiles/, plus their uncompressed and gzip-compressed sizes. Hidden files and REVISION are excluded. Run build first when you need fresh output. In a sets project, pass --set=<name> for JSON output; without it, normal output is grouped by set.
Common filters:
--keyPattern=<regex>--description=<regex>--withTests--withoutTests--archived=true|false--promotable=true|false
Target-aware behavior:
list --messages --target=<target>filters messages by the target'sincludeMessagesandexcludeMessages- when multiple targets are provided, the result is the union of messages included by those targets
Edge cases:
- pass exactly one of
--datafiles,--messages,--locales,--segments,--attributes,--targets, or--tests --withTestsand--withoutTestsare not supported for attributes
Read next:
find-usage#
Find authored relationships before changing or removing an entity.
$ npx messagevisor find-usage --message=checkout.title$ npx messagevisor find-usage --segment=premium-users$ npx messagevisor find-usage --attribute=account.plan$ npx messagevisor find-usage --locale=nl-NL$ npx messagevisor find-usage --format=number.money$ npx messagevisor find-usage --message=checkout.title --set=staging$ npx messagevisor find-usage --message=checkout.title --json --prettyPass exactly one query. Message, segment, attribute, and locale keys must exist; malformed format keys are rejected. In projects with sets, all sets are searched by default. Use --set=<set> to search one set. Structured JSON output for a sets project also requires selecting one set so the result has one unambiguous project scope.
Pass exactly one query option. Results identify the referencing entity and the relevant authoring path. Message queries include Targets and tests; segment and attribute queries include override and segment conditions; locale and format queries cover direct authored usage.
diff#
Render translation changes in a copy-review format instead of asking reviewers to interpret YAML or JSON diffs.
$ npx messagevisor diff$ npx messagevisor diff --format=markdown$ npx messagevisor diff --from=main --format=markdown$ npx messagevisor diff --from=release --to=feature$ npx messagevisor diff --set=staging --set=production$ npx messagevisor diff --resolved$ npx messagevisor diff --json --prettyThe default comparison follows the state of the current project:
- with uncommitted project changes, compare
HEADwith the working tree; - with a clean project, compare
mainormasterwith the current working tree (HEAD); - pass
--fromand--toto compare any local branch, remote-tracking branch, tag, or commit ref; - use
working-treeexplicitly as either side when needed.
The report includes base translations, override translations, translation workflow state changes, deprecation metadata, and override routing changes. Routing changes are shown separately when an override is added or removed, its conditions or segments change, the relative first-match order of existing overrides changes, or a referenced Segment definition changes.
It understands sets and accepts repeatable --set. --format=terminal is the human default, --format=markdown produces PR-friendly sections and tables, and --format=json (or --json) produces structured output.
Pass --resolved to add an impact view of effective copy after inheritTranslationsFrom is applied. This can reveal that editing one parent-locale translation changes several downstream locales. Each resolved value identifies the locale it was inherited from. Resolved comparison is opt-in because it can produce a much larger report; without it, diff stays focused on authored changes and routing.
diff reads Git snapshots without changing branches or writing project definitions. The requested refs must be available locally. In shallow CI checkouts, fetch the required history first; with actions/checkout, use fetch-depth: 0 when the comparison base is not included in the shallow clone.
It does not render ICU output; --resolved resolves locale inheritance only. Target-context specialization is a build-time concern and is not expanded into separate target-by-target rows in this authored-copy report.
find-duplicates#
Find active message keys that resolve to the same translation value.
Use this when:
- reviewing copy reuse before cleanup
- finding accidental duplicate labels across namespaces
- auditing inherited regional translations
Examples:
$ npx messagevisor find-duplicates$ npx messagevisor find-duplicates --locale=en-US$ npx messagevisor find-duplicates --set=staging$ npx messagevisor find-duplicates --locale=en-US --json --prettyBehavior notes:
- duplicate groups are scoped by locale
- locale translation inheritance is applied before comparing values
- overrides are ignored
- archived messages and empty translation values are ignored
- in sets-based projects, the command scans all sets independently unless
--set=<set>is passed
Read next:
create#
Scaffold entities from the CLI.
Use this when:
- creating many messages quickly
- generating empty locale or segment files to fill in later
- reducing repetitive path creation during authoring
Typical example:
$ npx messagevisor create --messages --keys=$'auth.signin\nauth.signout'Notes:
- this is a convenience authoring command, not a migration framework
- it is most useful for generating the initial file structure, then editing the authored content yourself
Read next:
examples#
Resolve and print authored examples from locales and messages.
Use this when:
- previewing example output without building an app
- checking matrix-expanded examples
- verifying that locale inheritance, target formats, and module behavior are producing the intended results
Examples:
$ npx messagevisor examples$ npx messagevisor examples --locale=en-US$ npx messagevisor examples --exampleIndex=2 --matrixIndex=3$ npx messagevisor examples --descriptionPattern=welcome --translationPattern=adult$ npx messagevisor examples --onlyMessages$ npx messagevisor examples --onlyLocales$ npx messagevisor examples --json --prettyImportant behaviors:
examplescovers both locale examples and message examples--onlyMessagesand--onlyLocalesnarrow the output to one class--locale=<locale>filters to one locale--exampleIndexand--matrixIndexare 1-based filters for already-authored example numbering- values that look like ISO date strings are coerced into
Dateobjects before evaluation so authored examples can drive date/time formatting cleanly - the same message and locale examples are also available in the generated Catalog, which is better for browsing and stakeholder review
Read next:
evaluate#
Evaluate one thing directly from the CLI. This is the fastest debugging command in the toolchain.
There are three modes:
--message=<key>: resolve an existing message key through a built target+locale datafile--rawMessage=<string>: evaluate an inline message string through the runtime modules for a locale--segment=<key>: evaluate a segment againstcontext
Examples:
$ npx messagevisor evaluate --message=auth.signin --locale=en-US$ npx messagevisor evaluate --message=dashboard.welcome --locale=en-US --values='{"name":"Ada"}'$ npx messagevisor evaluate --rawMessage="Hello {name}" --locale=en-US --values='{"name":"Ada"}'$ npx messagevisor evaluate --segment=platform-web --context='{"platform":"web"}'How the modes differ:
--messageuses the real built datafile path for the selected target and locale--rawMessageskips message lookup and formats the literal string through registered modules--segmentdoes not need--locale; it only needs segment definitions plus context
Common options:
--target=<target>--locale=<locale>--values=<json>--context=<json>--set=<set>--json--pretty
Edge cases:
- pass either
--messageor--rawMessage, not both --messageand--rawMessagerequire--locale--segmentworks without--locale- malformed JSON in
--valuesor--contextfails early
Read next:
benchmark#
Benchmark translation evaluation against a built target+locale datafile.
Use this when:
- comparing target sizes or override complexity
- measuring hot-path translation performance
- checking the effect of modules or context-heavy messages
Typical usage:
$ npx messagevisor benchmark --message=auth.signin --target=web --locale=en-US -n=1000Behavior notes:
- benchmark numbers are only meaningful when you keep target, locale, values, and modules stable between runs
- if you care about app startup cost too, combine this with build output inspection and catalog inspection
Read next:
build#
Generate runtime JSON datafiles.
Use this when:
- publishing translations for applications
- inspecting the exact target-filtered output the SDK will consume
- validating target-level format overrides and included-message sets
Examples:
$ npx messagevisor build$ npx messagevisor build --target=web --locale=en-US$ npx messagevisor build --set=production$ npx messagevisor build --showSizeWhat build does:
- resolves locale format inheritance
- applies target-level locale format overrides
- filters messages by target inclusion/exclusion rules
- includes only the attributes and segments needed by included overrides
- writes one datafile per target and locale combination
Key options:
--target=<target>--locale=<locale>--set=<set>--showSize--json--pretty--noStateFiles
Edge cases:
- in sets mode, some invocations require
--set - building a single target/locale pair is often the easiest way to debug a target-specific issue
- target context influences which overrides survive the build
- target files control datafile serialization with
pretty,stringify, andrevisionFromHash
Read next:
test#
Run Messagevisor project tests.
Supported test subjects:
- messages
- segments
- locales
- targets
Examples:
$ npx messagevisor test$ npx messagevisor test --keyPattern=welcome$ npx messagevisor test --assertionPattern=evaluation$ npx messagevisor test --onlyFailures$ npx messagevisor test --showDatafile$ npx messagevisor test --verbose$ npx messagevisor test --json --prettyWhat tests can do:
- message assertions evaluate resolved translations
- segment assertions verify segment matching against context
- locale assertions can verify resolved formats and evaluate
rawMessage - target assertions can verify included/excluded messages, resolved formats, and evaluate either
rawMessageormessage
Helpful filters:
--keyPattern=<regex>narrows the test file set--assertionPattern=<regex>narrows individual assertions by description--onlyFailureskeeps output short when you already know the suite is noisy--showDatafileis especially useful for target assertions
Behavior notes:
- matrix-expanded assertions are filtered after description expansion
- key-like fields stay literal in matrix expansion unless the assertion type explicitly supports placeholders there
- target assertion evaluation uses the actual built target datafile, so missing translations follow normal SDK behavior instead of producing a custom test-only error
Read next:
export#
Export translations to CSV.
Use this when:
- preparing files for translators
- reviewing translation status outside the repo
- exchanging direct and inherited translations in a spreadsheet workflow
Examples:
$ npx messagevisor export$ npx messagevisor export --locale=en-US --target=web$ npx messagevisor export --locale=en --locale=nl-NL --target=web$ npx messagevisor export --printUseful options:
--locale=<locale>; omit it for all locales, or repeat it for multiple locale columns--target=<target>--includeMessages=<pattern>--excludeMessages=<pattern>--excludeOverrides--withoutDescription--withoutStatus--onlyUntranslated--onlyDirectlyUntranslated--print--output=<path>--force--delimiter=<char>--bom--lineEnding=lf|crlf
Behavior notes:
- export status distinguishes direct, inherited, and missing translations
- repeated
--localeis useful for source/reference plus target handoff files - target filters apply before rows are emitted
--printwrites the CSV to stdout instead of creating a file
Read next:
import#
Import translations from CSV, or from a flat JSON object with --from-json.
Use this when:
- round-tripping a Messagevisor export through external translation work
- applying translated cells back into message and override translation maps
- previewing CSV changes before writing files
- pulling already available JSON translations into one locale
Examples:
$ npx messagevisor import exports/messagevisor-export-20260419T123456.csv$ npx messagevisor import --input=translator/nl.csv --apply$ npx messagevisor import --input=translator/nl.csv --locale=nl-NL --apply$ npx messagevisor import --input=translator/en-US.csv --locale=en-US --prune --apply$ npx messagevisor import vendor/new-copy.csv --create-missing$ npx messagevisor import translations.csv --set=staging$ npx messagevisor import translations.json --from-json --locale=nl-NL$ npx messagevisor import https://example.com/nl-NL.json --from-json --locale=nl-NL --apply$ npx messagevisor import payload.json --from-json --json-path=data.translations --locale=nl-NLUseful options:
--input=<path>--set=<set>--locale=<locale>--create-missing--apply--prune--from-json--json-path=<path>--delimiter=<char>--bom
Behavior notes:
- import expects the export-style CSV shape
- without
--locale, import reads all known locale columns in the CSV - repeat
--localeto import only selected locale columns --from-jsonexpects one flat object ofmessageKey: translationpairs and exactly one--locale--json-pathselects a nested object using dot-path syntax, such asdata.translationsimportpreviews changes by default and does not write files--applywrites imported translations to message files--pruneskips or removes direct translations when the imported value matches inherited copy--create-missingallows import to create unknown messages and unknown overrides; without it, unknown rows are skipped with warnings- when creating an override row, the base message must already exist or be created by another row in the same import
--createMissingis also accepted as a camelCase alias- override rows are mapped using the configured
exportOverrideKeySeparator - in sets projects, JSON import requires exactly one
--set=<set>
Read next:
generate-code#
Generate typed runtime helpers from your project.
Use this when:
- you want generated message key types or helpers
- you want a React-oriented codegen shape for app integration
Examples:
$ npx messagevisor generate-code --language typescript --out-dir src/generated$ npx messagevisor generate-code --language typescript --out-dir src/generated --reactBehavior notes:
- generated output depends on your current project definitions
- code generation complements the SDK; it does not replace datafile building
Read next:
prune#
Remove stale authoring data.
Use this when:
- cleaning unused translations
- removing dead format presets
- narrowing a project after target or locale changes
Examples:
$ npx messagevisor prune --translations$ npx messagevisor prune --translations --target=web --apply$ npx messagevisor prune --formats --locale=en-USBehavior notes:
- prune commands are intentionally selective; preview first, then apply
- target-aware pruning lets you ask "what is unused for this target?" rather than only "what is unused globally?"
Read next:
promote#
Copy authoring changes from one set to another.
Use this when:
- moving definitions through
dev -> staging -> production - reviewing whether one set can be promoted cleanly
- producing an audit trail for sets-based change movement
Examples:
$ npx messagevisor promote --from=dev --to=staging$ npx messagevisor promote --from=dev --to=staging --target=web$ npx messagevisor promote --from=dev --to=staging --excludeOverrides$ npx messagevisor promote --from=dev --to=staging --conflicts=fail$ npx messagevisor promote --from=dev --to=staging --showUnchanged$ npx messagevisor promote --from=dev --to=staging --apply$ npx messagevisor promote --from=dev --to=staging --apply --audit=markdownUseful options:
--from=<set>--to=<set>--target=<target>--locale=<locale>--includeMessages=<pattern>--excludeMessages=<pattern>--excludeOverrides--conflicts=source|destination|fail--allowEmpty--apply--audit=json|markdown--showUnchanged
Behavior notes:
promotepreviews changes by default and does not write files--applywrites the promotion to the destination set--auditwrites an audit file only when used with--apply- conflict handling is explicit because promotions can merge arrays and object structures, not just copy whole files
- projects can restrict allowed flows via
promotionFlows
Read next:
catalog#
Work with the generated project catalog.
Main entry points:
catalog: combined export + serve + watch flowcatalog export: generate static catalog filescatalog serve: serve the generated catalog locally
Examples:
$ npx messagevisor catalog$ npx messagevisor catalog --with-translation-search$ npx messagevisor catalog --with-duplicates$ npx messagevisor catalog --set=staging --set=production$ npx messagevisor catalog export$ npx messagevisor catalog export --with-translation-search$ npx messagevisor catalog export --with-duplicates$ npx messagevisor catalog export --set=production$ npx messagevisor catalog serve$ npx messagevisor catalog export --hashRouter$ npx messagevisor catalog serve --hashRouterRouting behavior:
- browser router is the default
- that means generated URLs are clean and do not include
# - use
--hashRouteronly when your host cannot fall back toindex.htmlfor deep routes
Translation search:
- by default, catalog generation skips the translation-value search index for faster exports on large projects
- use
--with-translation-searchwithcatalogorcatalog exportto enabletranslation:"keyword"searches in the message list catalog serveonly serves generated files; it does not build or change the translation search index
Duplicate reports:
- by default, catalog generation skips locale duplicate translation reports for faster exports on large projects
- use
--with-duplicateswithcatalogorcatalog exportto generate duplicate data and show locale Duplicates tabs catalog serveonly serves generated files; it does not build or change duplicate reports
Sets:
- in sets-based projects, catalog generation includes all sets by default
- pass
--set=<set>withcatalogorcatalog exportto generate only selected sets - repeat
--setto include multiple sets - the catalog still shows the set switcher when the project uses sets, even if only one set is selected
- the set switcher orders set names starting with
devfirst and set names starting withprodlast
Read next:
Troubleshooting patterns#
A translation looks wrong#
- Run
evaluate --message=... --target=... --locale=... - If the result depends on conditions, add
--context=... - If the message uses formatting or ICU syntax, confirm your project modules in
config - If the message is target-specific, build that target+locale pair and inspect the datafile or catalog
A segment does not match the way you expect#
- Run
evaluate --segment=... --context=... - Check the attribute schema and condition operators
- If the segment is only used in overrides, build or test the affected message/target path too
A target seems to be missing a message#
- Run
list --messages --target=<target> - Run
test --keyPattern=<target-or-message> - Build the target+locale pair and inspect the resulting datafile
- If you are using sets, make sure you are looking at the right
--set
An example or locale test is formatting differently than expected#
- Confirm locale format inheritance in Locales
- Check target-level format overrides in Targets
- Confirm runtime modules in Modules
- Re-run with
examples,evaluate, ortest --showDatafiledepending on whether you are debugging authoring examples, raw runtime behavior, or built output
Workflow recipes#
Validate a project before publishing datafiles#
$ npx messagevisor lint$ npx messagevisor test$ npx messagevisor build --showSizeDebug a raw ICU string for one locale#
$ npx messagevisor evaluate --rawMessage="{count, plural, one {# item} other {# items}}" --locale=en-US --values='{"count":2}'Inspect only locale examples#
$ npx messagevisor examples --onlyLocales --locale=en-US --json --prettyReview a target-specific issue#
$ npx messagevisor list --messages --target=web$ npx messagevisor test --keyPattern=web --showDatafile$ npx messagevisor build --target=web --locale=en-USGenerate and browse the catalog locally#
$ npx messagevisor catalog