StringLane in Claude Code
Install the plugin: an MCP server over your locale files, four slash commands, the skills, and a write guard that asks before Claude hand-edits a locale file. What the guard covers, what it deliberately does not, and how to remove it.
Last updated
Claude Code is one of eight hosts StringLane installs into, and one of three that take it as a plugin. This page is that plugin. For the other seven, and for what each one's write guard can actually do, see Agent hosts.
Four things, and the second is why this is a plugin rather than a line of configuration.
An MCP server over your localization files: inspect the project, plan what needs translating, validate a set of translations, apply them, add keys and locales.
A write guard. An MCP server only ever sees its own tool calls. It has no way to know an agent just wrote a locale file with Write, or with a shell command, and that has happened more than once in this project's history. The guard is a hook, so it sees both.
Four commands, listed below.
Three skills, for the parts no tool call finishes on its own: what each format can and cannot say, what adding a locale costs beyond the file, and what adding a string costs beyond the base locale.
Install#
/plugin marketplace add thebedcoder/stringlane-plugin
/plugin install stringlane@stringlane
Both lines are needed: the first registers the marketplace, the second installs from it. /plugin marketplace add clones a git repository, so the plugin lives in a public mirror rather than on npm.
Then:
/stringlane:setup
The plugin brings the MCP server and the write guard with it, but both call a stringlane binary that has to exist on your machine. /stringlane:setup finds out whether it does — and whether the copy it found is new enough to answer stringlane hook, which is the failure that looks exactly like working. It reads and reports; the one thing it can write is a package install, and it asks first.
Then, in a project with localization files:
/stringlane:init
It detects the project, shows you the config before writing it, reports what is translated and what is not, and offers one concrete piece of work. Every write is a separate yes.
The four commands#
On Codex CLI the same four arrive as skills, under the same names with a stringlane- prefix, because Codex does not load a commands/ directory.
What the guard does#
Two halves, covering different things on purpose.
Before an edit — Write, Edit, MultiEdit, NotebookEdit — StringLane is asked whether the file is one it manages. If it is, you get asked, with the sanctioned route named. It never refuses on its own, and anything it cannot decide is allowed. A guard that blocks when it is confused is a guard that gets turned off, and then it guards nothing.
After any tool runs, including a shell command, StringLane compares your locale files against a baseline taken when the session started, and reports what changed. It cannot block, because the write already happened. It tells you and the agent, and points at stringlane check.
Prevention covers
Write,Edit,MultiEditandNotebookEditonly. A shell command is covered after the fact, not prevented. Nothing in aBashtool call says which file it will touch — the path can be computed — so there is nothing to decide about before it runs. No completeness should be read into the prevention half.
It also will not notice a locale file written into a directory your project keeps no locale files in, and it cannot stop an agent that removes the hook. It is a guard against a confused agent, which is what actually goes wrong.
Adding a language is two jobs#
StringLane creates app_de.arb, or values-de/strings.xml, or the entry in your string catalog. The other half is in your app, and it is the half that decides whether anyone ever sees the translation:
- Flutter — if your
MaterialApplists locales asAppLocalizations.supportedLocales, there is nothing to do. If it lists them literally, German is not selectable until you add it. ThenCFBundleLocalizationsinInfo.pliston iOS, or the App Store will not list the language. - iOS — Xcode records localizations in the project file. An
de.lprojfolder Xcode does not know about is a correct file that never ships. - Android — the folder qualifier is usually enough. But a
localeFiltersorresourceConfigurationslist in your Gradle file strips the language out of the APK with a green build, and appearing in Settings has its own locale config. - i18next —
supportedLngsaccepts every language by default. If you have set it, a language missing from the array is rejected and falls back, and your JSON file sits on disk unread.
And in all four, a language picker with a hardcoded list.
Every one of these is optional, so none can be assumed. Miss one and you get the same symptom as having no translation at all, with a fully translated file in the repository.
The plugin's locale-wiring skill carries this per platform, so Claude raises the wiring instead of reporting the locale as done. /stringlane:init also scans for yours while it is already reading your codebase, and offers to write down what it found — the absences included, so a later session does not go looking for a picker you have never had. It goes in .stringlane/locale-wiring.md, and it asks first. Nothing here edits your app for you.
Turn the guard off#
The off switch matters as much as the guard, because a hook you cannot remove gets removed by uninstalling everything.
Take out just the hooks, leaving the MCP server:
stringlane setup hooks --host claude-code --removeIt removes StringLane's entries and leaves every other hook in that file exactly as it was. Or disable the whole plugin with /plugin.
To see what would be installed without installing it:
stringlane setup hooks --host claude-codeThat prints the exact JSON and the exact file it would go in, and writes nothing.
Without the plugin#
The plugin is a convenience. The same guard installs into any project:
stringlane setup hooks --host claude-code --scope project --apply--scope project writes .claude/settings.json in the repository, so your team gets the same guard. --scope user covers every project you open. Both back up what was there first and print where the backup went.
Claude Code is the only host where --apply writes. Everywhere else the setup commands print the change and you paste it, for the reason given in Agent hosts.
Windows#
The MCP server and the hooks work. The bundled resolver does not: it is a POSIX shell script, and Windows will not run it. That costs one convenience, not the plugin. Install the CLI yourself once and everything else behaves identically:
npm install -g @stringlane/cliFrequently asked questions
- What does the StringLane write guard actually block?
- It asks you before Write, Edit, MultiEdit or NotebookEdit changes a file it recognises as a locale file. It never refuses on its own, and anything it cannot decide is allowed. A shell command cannot be prevented, because nothing in the tool call says which file it will touch, so those are reported after the fact instead.
- How do I remove the StringLane hooks from Claude Code?
- Run stringlane setup hooks --host claude-code --remove. It takes out StringLane entries and leaves every other hook in that file exactly as it was. Disabling the whole plugin with /plugin also works.
Set Up StringLane in Any MCP Host
Next →Find Unused and Undefined Keys