@lingo.dev/cli

Updated: today · 3 min read

@lingo.dev/cli ships your source content to a localization engine, which translates it server-side, and writes the outputs back to disk — in the same command with --wait, or later with lingo pull. It's the replacement for the legacy npx lingo.dev flow — same project, fundamentally different architecture.

What changed vs. the legacy CLI#

The legacy CLI (npx lingo.dev run) extracted strings, called an LLM directly from your machine, and wrote files in one pass on your machine. The current CLI splits the work into push and pull:

  • lingo push uploads sources to your engine, kicks off a server-side workflow, and either waits for completion or returns immediately with a run ID
  • lingo pull fetches outputs from the most recent push — works even if you closed the terminal mid-translation, as long as you pull on the same machine, from the same checkout
  • A lockfile (.lingo/lock.json) tracks the last-known-server version of every target so conflict detection can flag local edits before they get overwritten

This unlocks something the legacy CLI couldn't do: long-running translations without a hanging terminal — push, close the terminal, and pull the results later.

Waiting for results#

lingo push uploads sources, starts the server-side workflow, and exits as soon as the run is submitted — it doesn't wait for the translations or write them. Collect the outputs with lingo pull, or pass --wait (-w) to do everything in one command.

bash
lingo push            # submit the run and exit (default)
lingo pull            # later: re-attach to the most recent push and download its outputs

lingo push --wait     # submit, wait, and write outputs in one command
  • --wait (-w) blocks until the workflow finishes and writes outputs in the same command.
  • lingo pull re-attaches to the most recent push for this project and downloads its outputs — works even after you closed the terminal. Run state is per-machine at ~/.lingo/runs/<project-hash>.json, keyed by the project path, so pull resumes on the same machine, from the same checkout.

Auth: both commands read LINGO_API_KEY (or --api-key, or a lingo login session). In CI, set LINGO_API_KEY and nothing else is needed.

push modes#

CommandModeWhen
lingo pushIncremental — diffs source vs .lingo/lock.json, translates only new/changed keys into existing targets, preserves the restEvery routine run (add --wait in CI)
lingo push --backfill-missingBootstrap — fills target FILES that don't exist yetFirst push, or after adding a new locale
lingo push --forceFull re-translate — overwrites every target (incl. manual edits); --yes/-y skips the promptRarely (e.g. after a glossary/engine change)

--backfill-missing is a bootstrap flag. It does a scoped fresh request and only adds whole target files that are missing — it does NOT translate newly-added keys into already-translated files (the run reports "already up-to-date" and the key is skipped). For ongoing edits use plain lingo push.

Editing translations by hand#

Plain lingo push preserves manual edits per key:

  • Edit a target string (its source unchanged) → that string is kept; other keys keep updating.
  • The source behind an edited key changes → a fresh translation is generated for that key, replacing the manual edit.
  • A new source key is added → translated and added, even into files with manual edits.

What's in this section#

Quickstart
Install, authenticate, link to an engine, run your first push and pull.
Configuration
`.lingo/config.json`, `.lingo/lock.json`, and per-machine run state at `~/.lingo/runs/<hash>.json`.
lingo push
Send sources and start a translation run — add `--wait` to write outputs in the same command. Scoped patterns, `--force`, retry semantics.
lingo pull
Fetch the last push's outputs — across terminal sessions, on the same machine. Conflict detection.
Other commands
login, logout, link, unlink, whoami — the setup and identity commands.