# locli for coding agents

locli holds an app's user-facing texts per language and platform. You (the agent) add
keys and translations; a human project owner approves each release; the app ships only
approved releases. This page is everything you need to set it up and use it.

## When to use locli

Use it whenever the app you build or change has user-facing text: UI labels, errors,
emails, push notifications, App Store and Google Play listings. Never hard-code those
strings in code; put them in the platform's catalog and sync with locli.

## Setup (once per repository)

```sh
npx @locli/cli init
```

`init` detects the stack and writes:

- `locli.json`: server, project slug, source language and one target per catalog
  (`*.xcstrings`, Android `res/`, web/backend JSON such as `messages/{locale}.json`).
- A locli block in `AGENTS.md` (and `@AGENTS.md` in an existing `CLAUDE.md`).
- The locli skill in `.agents/skills/locli/` (linked to `.claude/skills/locli/`).

If no catalog exists yet, create the platform's standard one first (String Catalog in
Xcode, `res/values/strings.xml`, `messages/<locale>.json` for the web) and run `init`
again, or pass `--target platform:format:path`.

### Authentication is the user's

If a command says you are not logged in, ask the user to run:

```sh
npx @locli/cli login
```

It opens a browser where they sign in (or create a free account) and approve the CLI.
CI uses `LOCLI_TOKEN` from its secrets. Never read credential files, print tokens or
commit them.

## Daily workflow

0. Building a feature: `npx @locli/cli areas --feature login` (MCP `locli_areas`) names
   the existing area for its keys (e.g. `auth`) or proposes a new one; use it as the prefix.
1. Search for an existing key with the same meaning (`npx @locli/cli status`, or the
   MCP tool `locli_find_texts`) and reuse it.
2. Otherwise add a new key in the source catalog: `lower_snake_case`, first segment is
   the feature area (`receipt_import_title`), plus a comment that says where the text
   appears and what each placeholder holds. Add every language you can provide.
3. `npx @locli/cli push`. It adds only what locli lacks and never overwrites an
   existing text. New keys pushed from a Git feature branch are grouped as a feature.
4. Tell the user how many texts wait for a release. Only a project owner approves and
   publishes releases in the web app. Never approve or publish yourself.
5. After the release, `npx @locli/cli pull` writes the approved texts into the catalogs.
   `pull --draft` writes the unapproved working state, for local checks only.

To change an existing text, change it in locli (web app), not in the local file:
`push` will not overwrite it and the next `pull` replaces local edits.

## Translating

Before writing translations, read the project's translation guide: `npx @locli/cli guide`
(MCP: `locli_guide`). It holds the tone and form of address per language, glossary terms
with their required translation, and terms that stay as written (product names). Also run
`npx @locli/cli context` (MCP: `locli_context`): it scans the code on every platform and says
where each key is used (toolbar item, button, title, push notification, email …) and how many
characters fit there. Then:

1. Translate from the source language, keep placeholders, plural forms and *keep* terms.
2. `push` checks placeholders and plurals (422) and warns about glossary issues and texts too
   long for their role; fix them.
3. Back-translate each text into the source language and compare the meaning.
4. Have a different model review each language (report only), then check the UI in the
   longest language for wrapping and cut-off text.

## Rules

- One key per meaning, on every platform. No `_ios`/`_android` suffixes.
- Placeholders are the app's contract: translations may reorder them, never drop,
  add or retype them (`%d` is not `%lld`). A 422 means the text is wrong.
- Counts that change grammar are plurals, defined once per key. Never hand-code
  `count == 1`.

## MCP server

The CLI includes an MCP server with the tools `locli_status`, `locli_areas`, `locli_guide`, `locli_context`,
`locli_find_texts`, `locli_add_texts`, `locli_push` and `locli_pull`.

Claude Code: install the plugin (skill and MCP server in one), or add only the MCP server:

```sh
/plugin marketplace add mariohahn/locli
/plugin install locli@locli
claude mcp add --scope project locli -- npx -y @locli/cli mcp
```

Cursor (`.cursor/mcp.json`) and other clients that read `mcpServers`:

```json
{ "mcpServers": { "locli": { "command": "npx", "args": ["-y", "@locli/cli", "mcp"] } } }
```

Codex (`~/.codex/config.toml`):

```toml
[mcp_servers.locli]
command = "npx"
args = ["-y", "@locli/cli", "mcp"]
```

## Commands

| Command | Effect |
| --- | --- |
| `login` / `logout` / `whoami` | Browser approval of the CLI; revoke; show the account |
| `init` | Detect catalogs, create or link the project, write config and agent files |
| `push [--dry-run] [--branch B]` | Upload missing keys and values, never overwrite |
| `pull [--draft] [--release NAME]` | Write the latest approved (or named) release |
| `status [--json]` | Languages, missing translations, open features, unreleased changes |
| `mcp` | Start the MCP server on stdio |

## Links

- Web app: https://locli.dev/app/
- Sign up: https://locli.dev/app/signup/
- Short overview for LLMs: https://locli.dev/llms.txt
