StringLane

    Type to search titles, sections and body text across all 58 pages.

    Reference

    Agent Hosts: What Yours Gets

    StringLane installs into eight coding agents. Which ones take a plugin, which take a pasted config, and what write guard each one can actually run, including the one where the honest answer is "nothing yet".

    Last updated

    StringLane's agent side is two separate things, and every host gets a different amount of each.

    The MCP server is eleven tools over the Model Context Protocol, so your agent reads and writes locale files through the same parser and validator the desktop app uses. It speaks a protocol, so it works the same in all eight.

    The write guard is the part that notices when your agent is about to hand-edit a locale file anyway, and gets in the way first. It is built out of whatever interception the host itself offers, and the eight hosts offer four different amounts. It does not work the same everywhere, and this page says which one you get.

    The table#

    HostInstallMCP serverWrite guard
    Claude Codepluginyesasks you first, plus after-the-fact detection
    Codex CLIpluginyesrefuses, and names the way to lift it, plus after-the-fact detection
    Gemini CLIextensionyesrefuses, and names the way to lift it
    Cursorplugin (local install), or config you pasteyesrefuses, and names the way to lift it
    Zedconfig you pasteyesconfirms, from Zed's own permission table
    OpenCodeconfig you pasteyesconfirms, from OpenCode's own permission table
    VS Code Copilotcode --add-mcpyesinstalls, and guards nothing yet
    Windsurfconfig you pasteyesrefuses, and names the way to lift it

    Every host also gets stringlane setup rules --apply, which writes three rules about locale files into your AGENTS.md between two markers it can take back out. That is the floor, and it applies on all eight.

    What "asks" and "refuses" actually mean#

    These are different promises and the difference is the host's, not StringLane's.

    Asks you first. Claude Code has an ask verdict in its hook protocol: the write is held, you are shown what is about to happen, and you decide. The model is told which tool to use instead.

    Refuses, and names the way to lift it. Codex CLI, Cursor, Gemini CLI and Windsurf have no ask. Codex reads Claude Code's hook envelope, but it accepts the word ask, fails the hook, and lets the edit through, so it is here rather than above. There is no click to give, so the guard's only options are allow and deny. StringLane denies, and the refusal message carries two things: the tool to use instead, and stringlane setup hooks --host <host> --remove. On Codex it also names /hooks, where you can disable the hook. On Cursor with the plugin, it names the plugin under Customize instead of --remove, because --remove edits a hooks file the plugin never wrote. A refusal you cannot lift is one people turn off for good.

    Confirms, from the host's own permission table. Zed and OpenCode run no hook StringLane speaks, but both have a permission table that can be asked to confirm on a path. stringlane setup guard --host zed prints an always_confirm block, and --host opencode prints a permission block, each in that host's own pattern language. Zed's patterns are regular expressions, OpenCode's are globs, and a locale path emitted verbatim is not a path but a pattern that looks like one.

    It is a snapshot of the locale files loaded when you ran it. A locale file added later is not covered until you run it again, and the printed block says so in its own first line.

    The honest absence#

    VS Code Copilot's hook installs and guards nothing. Its edit-tool names appear in its documentation rather than as hook values, so StringLane has no recorded list of them and the hook allows every write. Pasting it is harmless and inert. A guessed tool name would be worse, because it would look like a guard while never firing, so the list stays empty until a recording fills it, and setup hooks --host vscode prints that warning under the document itself.

    Why only Claude Code gets --apply#

    stringlane setup mcp and setup hooks print by default; --apply turns a print into a write, and today it does that for claude-code only. setup guard is different: it prints on every host it supports and has no write path at all. --apply there exits 2 with the block on stderr, because both permission files are JSONC and a JSON writer would drop your comments on the way back out.

    The gate is not on the feature. Every host below gets the real thing (the MCP entry, the hook document, the permission block) printed for the exact file it goes in, in that host's own shape. What is missing on the other seven is provenance: a captured session proving what the host actually sends and stores. StringLane will not merge into a file format nobody has run, because a config a host silently ignores is worse than no config: the host starts, lists no StringLane tools, and says nothing about why.

    A printed entry is not a lesser install. It is the same bytes --apply would have written. What you lose is the backup, the merge into what is already there, and the symlink checks, so read the file before you paste into it.

    Two rules cut across that.

    • setup rules and setup skills apply everywhere, because they write into your repository: AGENTS.md, and the skill folders under .agents/skills. Your files, in formats no host can misread.
    • --remove works everywhere, recorded or not. --apply is StringLane proposing a change to a file it has never seen your host write; --remove is you revoking something you pasted in yourself. On the hosts whose refusal is a deny, it is the refusal message's own way out for a hook you pasted.

    Per-host install#

    Claude Code#

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

    That is the whole install: the MCP server, four commands, the skills, and the write guard, which registers on PreToolUse, PostToolUse, PostToolUseFailure and SessionStart.

    Then run /stringlane:setup, which checks whether the stringlane binary the plugin calls actually exists on your machine, and whether the copy it found is new enough to answer stringlane hook: the failure that looks exactly like working.

    Its rules file is CLAUDE.md. AGENTS.md is read only through an @AGENTS.md import in CLAUDE.md, or a symlink.

    Codex CLI#

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

    The four slash commands arrive as skills, under the same names with a stringlane- prefix, because Codex does not load a commands/ directory. Its rules file is AGENTS.md.

    Then trust the guard. Codex does not run a plugin's hooks until you have reviewed and trusted them: open /hooks in Codex and trust the StringLane hook. Until you do, the MCP server works and nothing is guarded.

    For the MCP entry by hand, stringlane setup mcp --host codex prints Codex's own command rather than editing ~/.codex/config.toml, since that file is TOML and StringLane does not parse it.

    Gemini CLI#

    An extension, installed from the repository URL:

    gemini extensions install https://github.com/thebedcoder/stringlane-plugin

    Gemini installs the latest release of that repository. Each release carries one archive: the plugin directory, with gemini-extension.json at its root. Same bytes, same version as every other host gets, and Gemini's update check follows the release tags.

    The extension brings the MCP server and the context file, GEMINI.md. It declares no hooks, because an extension manifest is not where Gemini reads them from, so the guard is one more command:

    stringlane setup hooks --host gemini-cli

    That prints the hook document and the settings.json to paste it into.

    Cursor#

    A plugin, or a paste. The plugin brings the MCP server, the four commands, the skills and the write guard, which registers on preToolUse and sessionStart from its own hooks/hooks-cursor.json.

    The StringLane plugin is not listed in the Cursor Marketplace yet. Until it is, install it the way Cursor documents for a local plugin, then reload the window:

    git clone https://github.com/thebedcoder/stringlane-plugin
    mkdir -p ~/.cursor/plugins/local
    cp -R stringlane-plugin/plugins/stringlane ~/.cursor/plugins/local/stringlane

    The package is built to Cursor's plugin reference, and its hook and MCP commands have been run directly, but it has not yet been run inside Cursor itself. After the reload, check that the StringLane tools are listed; if they are not, remove the copied folder and use the pastes below. Use one route or the other, not both, or every write is guarded twice.

    To lift the plugin's guard, disable the plugin under Customize in Cursor. stringlane setup hooks --host cursor --remove does not reach a hook the plugin ships.

    Without the plugin, take the MCP entry and the guard as pastes:

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

    setup mcp prints the entry for ~/.cursor/mcp.json, or <project>/.cursor/mcp.json with --scope project. It also prints a cursor:// install link, built from the documented shape and not yet run; the paste above it is the part that is known to be right. setup hooks prints the document for ~/.cursor/hooks.json or <project>/.cursor/hooks.json.

    Zed, OpenCode, Windsurf#

    No plugin format this directory fits. Install the CLI, then ask it for the entry:

    npm install -g @stringlane/cli
    stringlane setup mcp --host zed

    --host takes zed, opencode or windsurf (and cursor, above), and --scope project prints the committed, per-repository entry where the host has one. Each report names the exact file, gives the entry in that host's own shape, and states what the host needs before it will read the file at all. These hosts want the entry under four different container keys, and one under the wrong key is not an error on any of them.

    For the guard: stringlane setup hooks --host windsurf, or stringlane setup guard --host zed|opencode. Every setup mcp report ends by naming the one for its host.

    Windsurf, now Devin Desktop, takes its hook in ~/.codeium/windsurf/hooks.json, or .windsurf/hooks.json with --scope project. Paste it exactly as printed, and in particular do not add ; exit 0 to the command: the refusal is the exit code, and that trailer turns every refusal into a pass. Devin Desktop reads .devin/hooks.json first and falls back to .windsurf/hooks.json only when that file is absent or defines no hooks, so if your project already has hooks in .devin/hooks.json, add the entry there instead.

    VS Code Copilot and GitHub Copilot CLI#

    No plugin. GitHub Copilot's plugin format is its own and shares nothing with this directory, so there is no command that would work. Install the CLI and take the MCP entry:

    npm install -g @stringlane/cli
    stringlane setup mcp --host vscode

    That prints VS Code's own one-liner for your user profile:

    code --add-mcp '{"name":"stringlane","command":"stringlane","args":["mcp","."]}'

    For one workspace it prints a .vscode/mcp.json entry instead. stringlane setup hooks --host vscode prints the hook document and the file it goes in, with the warning above attached, because that dialect has no recorded tool names and so allows every write.

    Skills on a host with no plugin#

    The Claude Code plugin comes with skills: for adding a new string without leaving every other language behind, for translating a locale, and for reviewing the result. On a host the plugin does not install into, stringlane setup skills shows them, and --apply writes them into your repository:

    stringlane setup skills --apply

    Each skill lands in its own stringlane-* folder under .agents/skills, so a team working in several editors commits one copy. Every file is stamped with the CLI version that wrote it, so running it again after an upgrade replaces a stale copy. A folder somebody has edited, one without the stamp, or one a newer CLI wrote is left alone and named, so a teammate a release behind cannot downgrade it. --remove deletes only unedited copies that carry the stamp, and stringlane check prints a line on stderr when the installed copies are older than the CLI running it.

    --host <host> changes nothing that is written. It adds that host's own note: whether it reads .agents/skills, and whether a plugin brings it the skills instead. StringLane's host table records every host except Claude Code as reading that folder, but none has been confirmed doing so in a recorded session, so check that the skills show up in yours.

    Windows#

    The MCP server and the hooks work. The resolver shim does not: it is a POSIX shell script, and Windows will not run it.

    In practice that costs one convenience rather than the plugin. The shim exists only to find StringLane when it is not already on PATH, so install it yourself once:

    npm install -g @stringlane/cli

    Once stringlane is on PATH the hooks and the MCP server call it directly and never reach the shim. What you lose without that step is the zero-install fallback: the hook command will not resolve and the guard stays silent rather than blocking anything. That is the designed failure rather than a broken one, but it does mean the guard is not protecting you, so the install is worth doing.

    Turning it off#

    stringlane setup hooks --host <host> --remove

    Works on every host with a hook you pasted in. On Claude Code, disabling the plugin with /plugin does the same thing to everything at once. On Codex, disable the hook under /hooks. On Cursor with the plugin, disable the plugin under Customize, because --remove does not reach a hook the plugin ships.

    The guard covers Write, Edit, MultiEdit and NotebookEdit before the fact. Besides your locale files, it guards an agent's edit to stringlane.yaml or .stringlane/source-stamps.json the same way, asking or refusing as your host allows, because an edit to the stamps file marks translations as current without anyone reviewing them. A shell write cannot be prevented, because nothing in the tool call says which file it will touch, so it is covered afterwards instead, by comparing your locale files against a baseline taken when the session started. No completeness is claimed for prevention, and none should be read into it.

    Frequently asked questions

    Which coding agents does StringLane support?
    Claude Code, Codex CLI, Gemini CLI, Cursor, Zed, OpenCode, VS Code Copilot and Windsurf each have a configuration StringLane prints by name, and the MCP server itself works in any host that speaks the protocol. Claude Code and Codex CLI install it as a plugin, Gemini CLI as an extension, and the rest take a config you paste. Cursor can also load the StringLane plugin as a local copy: it is not in the Cursor Marketplace, and the package has not yet been run inside Cursor.
    Why does stringlane setup mcp --apply only work for Claude Code?
    Because nobody has recorded what the other hosts actually write. StringLane will not merge into another program's config file until somebody has run that program and captured it, so on the other seven hosts --apply prints the entry and exits non-zero rather than writing. The printed entry is the same bytes --apply would have written, so a paste loses the backup and the merge, not the configuration.
    Does the StringLane write guard work in Cursor?
    Yes, from a hook document: stringlane setup hooks --host cursor prints one you paste into ~/.cursor/hooks.json. The StringLane plugin for Cursor, installed as a local copy, ships the same guard as hooks/hooks-cursor.json, but that package has not yet been run inside Cursor. Cursor's hook protocol has no "ask", so StringLane's refusal there is a deny whose own message names the tool to use instead and how to turn the guard off: the plugin under Customize for the plugin's hook, or the --remove command for a pasted one. That is a different promise from the ask-first guard on Claude Code, and the difference is stated rather than smoothed over.

    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