Every command walks up from the current directory to the nearest .lingo/config.json. That single rule is all you need to make the CLI work in a monorepo — you just decide where the config files live.
Option 1: one config at the root#
If your packages share a source locale and target locales, put one .lingo/config.json at the repo root and let its files patterns reach into each package:
{
"sourceLocale": "en",
"targetLocales": ["de", "fr"],
"files": [
{ "pattern": "apps/web/locales/en.json" },
{ "pattern": "packages/docs/content/en/**/*.md" }
]
}One lingo push from the root covers everything. The lockfile lives at the root too.
Option 2: a config per package#
When packages need different locales or engines, give each its own .lingo/config.json:
apps/web/.lingo/config.json # de, fr
apps/mobile/.lingo/config.json # de, fr, ja, koRun commands from inside a package (or cd in) — the CLI finds that package's config:
cd apps/mobile && lingo pushEach package has its own lockfile and links to its own engine independently.
CI per package#
In CI, point each package's job at its directory with --working-directory:
- run: npx @lingo.dev/cli@latest ci --step push --working-directory apps/web
- run: npx @lingo.dev/cli@latest ci --step push --working-directory apps/mobileSee CI/CD.
Running from a subdirectory
You don't have to cd to the package root by hand for local commands — running lingo push from anywhere inside a package walks up to that package's config and writes the lockfile back beside it.
