Set Up StringLane From Your Coding Agent
One paste. Hand this page to Claude Code, Codex, Cursor, Gemini or any MCP host and it works out which host it is in, installs what that host takes, and stops at every point where you should decide.
Last updated
Paste this at your coding agent:
Read https://stringlane.app/docs/cli/agent-setup.md and set up StringLane for this project.Everything below is the instruction set it will follow. It is worth reading first: it is short, and it is the thing that will be typing commands in your repository.
Instructions for the agent#
You are setting up StringLane in this repository: a localization engine that reads and writes ARB, iOS .strings/.stringsdict/.xcstrings, Android XML and JSON through one parser and one validator. The JSON can be i18next's, or the catalogs the Flutter packages easy_localization and slang use.
Propose; never auto-apply. Every step below that changes anything is a separate yes. State the exact command, say what it will do, and wait. If the user declines a step, carry on with the next one, because most of these are independent.
Do not edit locale files directly at any point, including before StringLane is installed. Four of the five formats escape, prefix or nest their values, so the bytes on disk are not the string.
Step 1: Is there anything to localize here?#
Look for locale files: *.arb, *.xcstrings, *.strings, res/values*/strings.xml, or a locales/ directory of JSON. In a Flutter project, also look for JSON catalogs: assets/translations/*.json or assets/langs/*.json (easy_localization), and *.i18n.json under lib/i18n/ or assets/i18n/ (slang). If you find none, say so and stop. StringLane has nothing to do in a repository with no localization, and installing it there is noise.
slang can also keep its catalogs as YAML or CSV. StringLane does not read those yet, so if they are all the project has, say that and stop.
Step 2: Is the CLI already installed?#
stringlane --versionFour outcomes, and the second is the one that gets misread:
- A version number. Go to step 3.
- Nothing at all, and exit 0. StringLane is not installed. On a host where the plugin is active, its resolver is on
PATHand deliberately succeeds in silence when it finds nothing, because a resolver that failed loudly would look to the hook protocol like a guard refusing an edit. Do not read exit 0 as installed. - An
npmerror, a 404 or no network. Say which, and stop. Retrying changes neither. command not found. Nothing is installed and no resolver is onPATH. Propose the install below.
To install, propose this and wait for a yes:
npm install -g @stringlane/cliIt needs Node 22 or newer, and it is one JavaScript file with no runtime dependencies.
Step 3: Which host are you running in?#
Work it out from what you can see: your own name, the directory your configuration lives in, the tool names you were given. Then take your row, and only yours.
If you cannot tell which host you are, ask. Guessing wrong writes a config file the real host never reads, which looks identical to working.
On Claude Code and Codex CLI, the plugin brings the MCP server and the write guard together, so step 4 is already done. Step 5 still applies: no plugin writes the rules file. On Codex, the guard still has to be trusted first (step 4). Gemini CLI's extension brings the MCP server but not the guard, so step 4 still applies there. If the user chose the Cursor plugin, have them reload the window and confirm the StringLane tools are listed before you tell them anything is installed. If the tools are not listed, have them remove the copied folder and take the setup mcp and setup hooks route instead. Never both: that guards every write twice.
On every other host, setup mcp prints the entry and the exact file it belongs in. It does not write it, and --apply will not either: StringLane only merges into a config file for a host somebody has recorded, which today is Claude Code. Show the user the printed block and the path, and let them paste it. Then tell them the host has to be restarted before it will load a new MCP server. The report ends by naming the command for that host's write guard, which is step 4.
Step 4: The write guard#
This is the part an MCP server cannot do for itself. The server sees only its own tool calls; it has no idea you wrote de.arb a moment ago with a file tool. A hook does.
stringlane setup hooks --host <your host>It prints the hook document and the file to paste it into. Report both, and say which of these your host gets, because they are different promises:
- Claude Code: the write is held and the user is asked. Installed with the plugin; nothing more to do.
- Codex CLI: its hook protocol has no "ask", so the write is refused, and the refusal names how to lift it. Installed with the plugin, but Codex runs a plugin's hooks only after the user trusts them: tell the user to open
/hooksin Codex and trust the StringLane hook. Until they do, nothing is guarded. - Gemini CLI, Cursor, Windsurf: their hook protocol has no "ask", so the write is refused. The refusal names the tool to use instead and the command to remove the guard. If the user installed the Cursor plugin and its tools are listed, its guard ships with it; do not paste a second one. That guard is lifted by disabling the plugin under Customize in Cursor, not by
--remove. On Windsurf, the user pastes the hook exactly as printed:; exit 0added to the command turns every refusal into a pass. - Zed, OpenCode: no hook StringLane speaks. Run
stringlane setup guard --host zedor--host opencodeinstead; it prints a block for that host's own permission table. - VS Code Copilot: the hook installs and guards nothing yet, because its edit-tool names are not available as hook values. Say so plainly rather than implying protection.
Whatever you paste in, stringlane setup hooks --host <host> --remove takes it back out, on every host. A hook the Cursor plugin ships is the exception: it comes out when the plugin is disabled under Customize.
Step 5: The rules file#
This one writes into the user's own repository, so it works on every host:
stringlane setup rules --applyIt adds three rules about locale files to AGENTS.md, between two HTML-comment markers. Everything outside the markers is untouched, running it twice still leaves one block, and --remove takes exactly that block back out. Propose it. It writes without a paste, like the skills step below, because the file is in the user's repository.
Step 6: Skills, on a host with no plugin#
Skip this on Claude Code, Codex CLI, and Cursor with the plugin installed: the plugin brings the skills. On any other host, propose:
stringlane setup skills --host <your host> --applyIt writes the plugin's skills (adding a new string, translating a locale, reviewing the result) into .agents/skills, one stringlane-* folder each, in the user's repository. --host changes nothing that is written; it adds that host's note on whether it reads .agents/skills. None of the hosts has been confirmed reading that folder in a recorded session, so tell the user to check that the skills show up. --remove deletes only the copies nobody has edited.
Step 7: The project itself#
stringlane initDetects the format and the path, and writes them to stringlane.yaml. It asks first. Show the user what it detected before confirming, because a wrong guess here is wrong for every later command.
In a new project that loads cleanly, init also turns on source stamps: it writes sourceStamps: true into stringlane.yaml and creates .stringlane/source-stamps.json, which records the English each translation was confirmed against, so check can later report translations that went stale. Tell the user three things before they confirm:
- it stamps every existing translation as current against today's English, unreviewed, because it cannot know whether they were current before today;
- both files must be committed, or
checkexits 2 in CI; - confirming translations later is theirs to do with
stringlane accept. There is no MCP tool for it, on purpose: do not runstringlane acceptyourself, even with--yes, unless the user asks you to.
Then get the state of things:
stringlane checkThe first line names the base locale. base en (detected) means StringLane guessed it from the file names. If that is not the project's source language, ask the user, then add baseLocale: <code> to stringlane.yaml, spelled exactly as it appears in the locale table check prints.
Report what comes back: which locales are behind, and which findings are structural. Do not start fixing them in this conversation unless asked.
Step 8: Give it context, once#
If prepare_translation_plan reports keysWithoutDescription above zero, or stringlane check shows many locales at once, the highest-value thing you can do next is not translating. It is writing down what the product is and what each key means.
You have read this codebase. That context is worth more here than anywhere else, and nobody recovers it later:
set_project_context(orstringlane context --from) records what the product is, how it should sound, per-locale notes, and terms that must never be translated.describe_keys(orstringlane describe) records what individual keys are for. Translating a bare"Close"is a guess about part of speech, gender and register, and it is the single largest source of wrong translations.
Propose both. Neither is required, and both improve every locale and every later session.
Then stop#
Setup is done. Tell the user what is installed, what the guard on their host does and does not cover, and what stringlane check found. Do not begin translating unless they ask.
When they do, it is three calls in order (prepare_translation_plan, validate_translations, apply_translations), and the agent workflow is the page for it.
For the human reading this#
Three things worth knowing about what you handed your agent.
Nothing here installs silently. The CLI's setup commands print by default; --apply on setup mcp and setup hooks writes only on Claude Code, and only into files whose format has been recorded from a real session. setup rules and setup skills write into your own repository on every host. Everywhere else the change is bytes on your screen that you paste yourself, which means you read it first.
The write guard is not one feature. It is built out of whatever each host lets StringLane intercept, and the eight hosts offer four different amounts, including one where the answer is "nothing yet". Agent hosts has the table.
--remove always works on what you pasted, on every host, whether or not --apply did. Refusing to install is cautious; refusing to uninstall is a trap.
Frequently asked questions
- How do I set up StringLane without reading the docs?
- Paste "Read https://stringlane.app/docs/cli/agent-setup.md and set up StringLane for this project." at your coding agent. The page is written as instructions: the agent works out which host it is running in, proposes the install for that host, and asks before every command that changes anything.
- Will my agent install things without asking?
- Not if it follows this page. Every step here says to propose the exact command and wait for a yes before running it. StringLane's own setup commands print by default and write only with --apply, and --apply works on Claude Code alone, so on every other host the change is a paste you make yourself.
Free ยท In your coding agent
Run the same checks from your coding agent
Paste this into Claude Code, Cursor, Codex or five other agents. It sets up the CLI and MCP server for this project, proposing each command and waiting for your yes.
Read https://stringlane.app/docs/cli/agent-setup.md and set up StringLane for this project.Or install it yourself:
npm install -g @stringlane/cli