Skip to content

Comvi CLI

View .md

@comvi/cli moves translations between your repository and your Comvi project and generates a TypeScript declaration from the project’s keys.

Terminal window
npm install -D @comvi/cli

Run it as npx comvi <command> once it is a dev dependency, or as npx --package @comvi/cli comvi <command> with nothing installed.

Terminal
export COMVI_API_KEY=comvi_xxxxxxxxxxxxxxxx
npx comvi pull

Every command reads COMVI_API_KEY. The key selects the project, so there is no project id to configure. Create one under API keys. The CLI also loads the nearest .env file before each command, walking up from the working directory and stopping at the first package.json, so COMVI_API_KEY=... in .env works with no wrapper. Real environment variables always win over the file.

Variable Effect
COMVI_API_KEY API key. Overrides apiKey in the config file
COMVI_API_BASE_URL Overrides apiBaseUrl in the config file
COMVI_NO_ENV=1 Skip auto-loading .env, same as --no-dotenv
COMVI_DEBUG=1 Print to stderr which .env was loaded and how many entries it added or skipped
Terminal
npx comvi init
.comvirc.json
{
"apiBaseUrl": "https://api.comvi.io",
"outputPath": "src/types/i18n.d.ts",
"strictParams": true,
"translationsPath": "./src/locales",
"fileTemplate": "{namespace}/{languageTag}.json",
"format": "json",
"locales": ["en", "de"],
"namespaces": ["common", "auth"],
"push": { "forceMode": "ask" },
"pull": { "emptyDir": false }
}

comvi init writes .comvirc.json in the current directory without locales or namespaces; add those by hand. It does write push and pull with their defaults, "forceMode": "ask" and "emptyDir": false. The file is safe to commit because the key stays in the environment. Commands find it by walking up from the working directory and stopping at the first package.json, so in a monorepo each package needs its own file or an explicit --config ../../.comvirc.json.

Field Default Meaning
apiKey $COMVI_API_KEY API key. Prefer the environment variable
apiBaseUrl https://api.comvi.io Comvi API base URL
outputPath src/types/i18n.d.ts Where comvi typegen writes the declaration
strictParams true false makes every interpolation parameter optional
augment package the app declares Module the declaration augments, for a private wrapper package. See Type-check translation keys
translationsPath ./src/locales Directory for local translation files
fileTemplate {namespace}/{languageTag}.json File layout for pull and push. With the default template the default namespace lives at the root as {languageTag}.json; a custom template is matched literally. Must contain {languageTag} and {namespace} once each and end in .json
format json Translation file format. Only json exists
locales all project locales Restrict pull and push to these BCP-47 codes (pt-BR, zh-Hans). --locale replaces the list
namespaces all namespaces Restrict pull and push to these namespaces. --ns replaces the list
push.forceMode ask Conflict handling for comvi push: override, keep, ask or abort
pull.emptyDir false Clear the pulled locales and namespaces after a successful fetch

strictParams and pull.emptyDir must be JSON booleans: the string "false" fails validation with exit 4 before any command opens a connection. An empty locales or namespaces list, a duplicate, or a non-string entry fails the same way. So does a field the config does not have: the legacy languages and defaultNsName are rejected by name, with locales named as the replacement for the first; the default namespace comes from the project.

Flag Default Meaning
-k, --api-key <key> none Write the key into the file. Prints a warning: arguments show up in process listings and shell history
-u, --api-url <url> https://api.comvi.io apiBaseUrl to write. A malformed URL exits 4 and writes nothing
-o, --output <path> src/types/i18n.d.ts outputPath to write
--no-strict-params off Write strictParams: false
--translations-path <path> ./src/locales translationsPath to write
--file-template <template> {namespace}/{languageTag}.json fileTemplate to write
--force off Overwrite an existing .comvirc.json

An existing file is left untouched and the command exits 1. --force rewrites the whole file, dropping any locales and namespaces and resetting push and pull to their defaults. When a key is set, init validates it against the platform; a failed validation is a warning and the file is still written.

Command Purpose
comvi pull Download translations from the project to local JSON files
comvi push Upload local translation files to the project
comvi typegen Generate a TypeScript declaration from the project’s keys
Flag Meaning
-V, --version Print the installed @comvi/cli version
-h, --help Print usage for the program or one command
--dotenv <path> Load one .env file instead of auto-discovery. A missing file exits 4
--no-dotenv Skip auto-loading .env

The flag is --dotenv, not --env-file: Node claims --env-file across the whole command line and exits 9 on a missing file before the CLI starts.

Code Meaning
0 Success
1 General error: missing .comvirc.json, auth failure, network error, failed generation
2 comvi typegen --check only: the check could not run because the API was unreachable, timed out, rejected the key or returned something unusable
4 Validation error: missing API key, malformed config JSON or field, a translation file with a non-string value or a key defined both flat and nested, a locale or namespace the project does not have, an unknown --force-mode, or a --dotenv file that does not exist

A missing .comvirc.json exits 1; an invalid one exits 4.