StringLane

StringLane CLI

Your build should know
before your users do

The same loop the desktop app runs, without the window. It reports what is missing and what is broken and sets an exit code. It serves your project to a coding agent that can add keys, translate and write back through the same checks. And it can translate the gaps itself with your own key. Nothing is written unchecked.

$npm install -g @stringlane/cli

Node 22 or newer. Free, with no key and no activation.

$ stringlane check . xcstrings · single-origin · base en4 locales · 10 keys · 64% complete   de      9/11       2 missing  en      11/11      complete  fr      9/12       3 missing  uk      1/13       12 missing 8 errors · 3 warnings · 0 info  warning  untranslated  de/app_name:      Key "app_name" in "de" appears to be      untranslated (same as base)  warning  punctuation_mismatch  fr/greeting:      Key "greeting" in "fr" needs a      non-breaking space before "!" — found      a plain space before "!"  error    missing_key   fr/items_count[many]:      Plural quantity "many" for "items_count"      is missing in "fr"  …8 more $ echo $?1
Real output from stringlane 0.3.1 on a sample Xcode String Catalog project with four locales. Abbreviated where marked, plus two omissions: a second untranslated warning identical to the first, and a closing note that this fixture has no source code to scan for unused keys.

Where it runs

Three ways in, one answer

The same report, whether a person asked for it, a pipeline did, or an agent did.

In your terminal

Point it at a folder and it tells you which locales are behind, which keys are missing, which translations are structurally broken, and which keys your source code no longer calls. It writes nothing while doing it.

stringlane check .Inspect and check

In your coding agent

stringlane mcp serves the project over the Model Context Protocol: ten tools, five of which write, and your agent asks you before each of those runs, the same way it asks before editing a file.

stringlane setup mcp --host cursorSet up your agent

In CI

Exit 0 clean, 1 issues, 2 could not run, 3 something it depends on did not answer: a broken gate and a failing gate are different answers. Add --json for a machine-readable report, and a committed baseline so an unclean project can adopt the gate today.

stringlane check . --jsonRun it in CI

Agents

Eight hosts. Three ways in.

The MCP server speaks a protocol, so it runs in any host that speaks it. How it gets installed is the host’s decision, and StringLane prints the real configuration for the exact file it belongs in either way.

A plugin

Claude Code · Codex CLI

One install brings the MCP server, the write guard, four commands and the skills that cover the parts no tool call finishes on its own.

/plugin marketplace add thebedcoder/stringlane-plugin
/plugin install stringlane@stringlane

Codex takes the same two lines with codex plugin in front of them.

An extension

Gemini CLI

Gemini reads an extension manifest from a path. It brings the MCP server and the localization rules; the write guard is one more command.

$git clone https://github.com/thebedcoder/stringlane-plugin
$gemini extensions install ./stringlane-plugin/plugins/stringlane

Then stringlane setup hooks --host gemini-cli for the guard.

A config you paste

Cursor · Zed · OpenCode · VS Code Copilot · Windsurf

No plugin format this directory fits, so the CLI prints the entry in that host’s own shape and names the exact file it goes in. Same server, same version, one paste.

$npm install -g @stringlane/cli
$stringlane setup mcp --host cursor

--host also takes zed, opencode, vscode and windsurf.

Every host gets the real configuration, printed for the exact file it belongs in. Claude Code is the one host StringLane writes it for you. Everywhere else the command prints the bytes and names the file, so a paste writes nothing you did not read first — and --remove takes it back out on every host, recorded or not. What each of the eight gets.

Or let the agent set itself up

Paste this at your coding agent and it will work out which host it is running in, install what that host takes, and stop at every point where you should decide.

Read https://stringlane.app/docs/cli/agent-setup.md and set up StringLane for this project.

It proposes; it installs nothing without a yes. Read it first.

AI

Two modes, and the difference matters

StringLane does the reading, the validating and the writing. Which model does the translating is the thing you choose, and it changes what leaves your machine.

Your agent’s model

In agent mode there is no provider key, because there is no provider. Your coding agent is already the model: StringLane hands it exactly what needs translating with the context to do it well, checks what comes back, and writes it only when you say so. Your strings go to the agent that started the server, running on your machine over stdin and stdout, and nowhere else.

Set up an agent

Your own provider key

stringlane update translates the missing strings itself, through a provider you configure: OpenAI, Anthropic, Google, Groq, Mistral, DeepSeek, xAI, or a local runner such as Ollama or LM Studio, in which case nothing leaves the machine. It is the only command that spends money, and it asks before it does. The key is read from your environment and is never written to a config file, a log or a report.

Translate with your key

Safety

Designed to refuse

An agent that edits locale files by hand gets escaping, plural categories and file layout subtly wrong, then reports success. The point of this tool is the set of things it will not do.

  • Four commands cannot touch your repository

    inspect, check, plan and validate write nothing into your project: not a lock file, not a re-saved locale file, not a byte. The test suite snapshots every file’s contents, size and modification time before and after, on Linux, macOS and Windows. What check and scan do write is a source-scan cache, and it goes in StringLane’s own state directory outside your repository, never in it.

  • A plan expires

    Before writing, apply re-reads every file the plan could touch and compares it to what was there when the plan was made. Edit a string, land a teammate’s branch, run a formatter, and it refuses with STALE_PLAN naming what moved, rather than overwriting work it never read.

    $ stringlane plan . --json --out plan.json$ stringlane apply . --plan plan.json \      --candidates cand.json --yes NOTHING WAS WRITTEN.the project changed since this plan was created:  "Localizable.xcstrings". Build a new plan.  at Localizable.xcstrings(STALE_PLAN) $ echo $?2
    Re-verified against stringlane 0.3.1. Between the two commands, the base string for cancel_button changed. Omitted: the plan summary line, and two advisory blocks about issues already in the fixture. Nothing else is.
  • All or nothing

    Every file it intends to produce is built in memory, parsed back and validated as the project would be afterwards, before a single byte lands. One structural error anywhere and nothing is written.

  • Nothing leaves the project root

    Not the config, not the baseline, not --output, not a path named inside a plan file. A repository that ships a symlink does not get to choose where an agent’s translations land.

The write guard adds one more layer, and states its own limit: it stops an agent hand-editing a locale file with a file tool, and reports after the fact when a shell command changes one. Nothing in a shell tool call says which file it will touch, so prevention there is not something anyone can offer. How it stops the write is the host’s to decide, not StringLane’s: where the host’s hook protocol can put the question to a person it asks, and where it cannot it refuses and names the command that lifts it. How the guard works, per host.

Scope

What it covers, and what it does not

Runs where you do

Linux, macOS and Windows each run the full suite on every change, because a local binary’s failures are mostly platform-shaped. It needs Node 22 or newer, and it is one JavaScript file with no dependencies to install.

What it deliberately is not

There is no daemon and nothing watches your project: commands start, do their work and exit. It does not check how a string looks in your running app; that is the human step, and the desktop app is where you do it. There is no IDE extension. And it will not edit another program’s config file until somebody has run that program and recorded what it writes, which today means Claude Code — everywhere else the setup commands print the change and leave it to you.

Pricing

Free, and separate from the app

No licence key, no activation, no account, and no limit on machines, projects or CI runs. It is versioned separately from the desktop app and licensed separately from it: buying one grants nothing on the other, in either direction. AI translation, when you use it, is billed by your own provider.

FAQ

Frequently asked questions

Is the CLI actually free, or free for now?
Free, today, with no asterisk on the usage: no licence key, no activation, no account, and no limit on machines, projects or CI runs, including at work. It is versioned separately from the desktop app precisely so the two are not entangled, and buying one grants nothing on the other in either direction. What we will not do is promise a price for a product still finding its shape, so “free forever” is not a claim you will find here. It is free software to use, not open-source software: the terms ship in the package.
Will it edit my files without asking?
inspect, check, plan and validate write nothing into your repository: not a lock file, not a re-saved locale file, not a byte. (check keeps a source-scan cache between runs, in StringLane's own state directory rather than in your project.) The commands that do write ask first, and refuse outright when there is no terminal to ask at unless you passed --yes, so a CI job cannot commit a decision nobody made. Over MCP the line is drawn by your agent host: it asks you before any of the five writing tools runs, the same way it asks before editing a file. There is no flag the model fills in on your behalf. An earlier version had one, and it was removed because a field the agent sets itself is not consent.
Do I need an AI provider key?
Only for stringlane update, which is the one command that talks to a model and the one that spends money, and it asks before it does. Everything else runs without a key, including the whole agent workflow: in agent mode the model is the one your agent already uses. When you do use update, the key is read from your environment and nowhere else: never from stringlane.yaml, never written to a config file, a keychain, a log, or any report it produces.
Which coding agents does it work with?
The MCP server works in any host that speaks the protocol, and eight of them have a configuration StringLane writes out for you by name: Claude Code, Codex CLI, Gemini CLI, Cursor, Zed, OpenCode, VS Code Copilot and Windsurf. stringlane setup mcp --host <host> prints the entry in that host's own shape and names the exact file it belongs in. Claude Code is the one where --apply then writes it, after backing the file up; everywhere else it prints and you paste, because StringLane will not merge into a file format nobody has run yet. The write guard is narrower still and differs per host. What each host gets.
My project has hundreds of existing issues. Can I still gate CI on this?
Yes, but record where you are first. stringlane baseline write writes today's findings to .stringlane/baseline.yaml; commit it, and check then fails only on issues that are new. Accepted issues are still counted and printed on every run rather than hidden, a suppressed entry is reported as stale once you fix the underlying problem, and nothing expires on a timer. A gate that turns red on a date nobody chose is a gate that gets switched off.
Does the CLI send usage data?
Yes, and it tells you so on its first run on a machine, before it sends anything: one event per command with the command name, whether it succeeded, and a rough duration, and never your arguments, paths, keys or strings. Turn it off with stringlane telemetry off, or STRINGLANE_TELEMETRY=0 or DO_NOT_TRACK=1 in your environment. It sends nothing at all when it detects CI, and no environment variable can switch it back on over a stored opt-out. The full policy.
Does it run on Windows and Linux?
Yes. Linux, macOS and Windows each run the full test suite on every change, because the failures a local binary has are mostly platform-shaped. It needs Node 22. One caveat, on Windows only: the plugin's bundled resolver is a POSIX shell script and will not run there, so install the CLI globally once yourself and the MCP server and hooks then behave identically.

Still have questions? Email us at support@stringlane.app