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 two where the honest answer is "nothing yet" and "none".
Last updated
StringLane's agent side is two separate things, and every host gets a different amount of each.
The MCP server is ten 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#
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 and Codex CLI have an ask verdict in their 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. Codex implements the Claude Code hook schema verbatim, so this is the same experience rather than an approximation of it.
Refuses, and names the way to lift it. Cursor and Gemini CLI have no ask. 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. 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 two honest absences#
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.
Windsurf gets no guard, and that is a decision rather than a gap. Its pre-write hook is exit-code only, with no channel back to the model. A silent block teaches the agent nothing, so it routes around the block through the shell — which is worse than not blocking, because you believe you are guarded.
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 rulesapplies everywhere, because it writesAGENTS.md: your file, in your repository, in a format no host can misread.--removeworks everywhere, recorded or not.--applyis StringLane proposing a change to a file it has never seen your host write;--removeis you revoking something you pasted in yourself. On the hosts whose refusal is adeny, it is the refusal message's own way out.
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@stringlaneThe 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.
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, and it installs from a path rather than a repository URL:
git clone https://github.com/thebedcoder/stringlane-plugin
gemini extensions install ./stringlane-plugin/plugins/stringlanegemini extensions install <repository-url> expects the manifest at the repository root. StringLane keeps the plugin in a subdirectory so one copy serves every host, so the local-path form above is the one to use — same bytes, same version.
The extension brings the MCP server and the context file. 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-cliCursor, 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 cursor--host takes cursor, zed, opencode or windsurf, 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.
Cursor 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.
For the guard: stringlane setup hooks --host cursor, or stringlane setup guard --host zed|opencode. Windsurf has none, for the reason above.
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 vscodeThat 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.
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/cliOnce 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> --removeWorks on every host with a hook. On Claude Code, disabling the plugin with /plugin does the same thing to everything at once.
The guard covers Write, Edit, MultiEdit and NotebookEdit before the fact. A shell write cannot be prevented — 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.
- 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 you paste into ~/.cursor/hooks.json. 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 the command that removes the guard. That is a different promise from the ask-first guard on Claude Code, and the difference is stated rather than smoothed over.
Exit Codes and the JSON Report