StringLane

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

    How-To

    Translate With Your Own Provider Key

    stringlane update fills the missing strings using an API key you supply through the environment. StringLane never stores it, every translation goes through the same validation gate, and the write is all or nothing.

    Last updated

    The plan → agent → apply round trip is the right shape when something else is doing the translating. If all you want is the missing strings filled in, that is three commands and a file to shuttle around.

    export OPENAI_API_KEY=sk-…
    stringlane update .

    It plans, translates, checks every translation against the same rules stringlane check applies, and writes them, all or nothing. This is not a shortcut past the gate; it is the same gate with the plan and the candidates kept in memory instead of on your disk.

    The key is yours, and it is never stored#

    update reads your key from the environment and nowhere else. It is not in stringlane.yaml, there is no ~/.stringlanerc, and nothing is written to a keychain, a config file, a log, or a plan.

    For each provider, two variables are consulted in this order:

    ProviderStringLane's variableThe conventional one
    openai (default)STRINGLANE_OPENAI_API_KEYOPENAI_API_KEY
    anthropicSTRINGLANE_ANTHROPIC_API_KEYANTHROPIC_API_KEY
    googleSTRINGLANE_GOOGLE_API_KEYGOOGLE_GENERATIVE_AI_API_KEY
    groqSTRINGLANE_GROQ_API_KEYGROQ_API_KEY
    mistralSTRINGLANE_MISTRAL_API_KEYMISTRAL_API_KEY
    deepseekSTRINGLANE_DEEPSEEK_API_KEYDEEPSEEK_API_KEY
    xaiSTRINGLANE_XAI_API_KEYXAI_API_KEY
    localnone neededLM Studio and Ollama need no key

    The StringLane-namespaced name wins when both are set, which is how you point stringlane at one account while the rest of your shell keeps using another.

    A variable set to the empty string counts as not set. FOO= in a CI config is how a key gets accidentally unset, and treating it as present would send an empty token to your provider and report the resulting 401 as something else.

    If no key is found, update stops before it reads your project: no plan, no model call, no file touched. The message names the two variables it looked for and neither value, because there are no values to name.

    Choosing a provider and model#

    stringlane update . --provider anthropic --model claude-haiku-4-5

    Flags first, then STRINGLANE_AI_PROVIDER and STRINGLANE_AI_MODEL, then the provider's default.

    A provider name it does not recognise is a refusal, not a fallback. Running the default for somebody who typed --provider opnai spends their money somewhere they did not name, and the typo would only surface in the bill.

    For a local runner:

    export STRINGLANE_AI_BASE_URL=http://localhost:11434/v1
    stringlane update . --provider local --model llama3.2

    Provider and model deliberately do not live in stringlane.yaml. That file is committed project intent, and two people on one repository legitimately use different providers: one has an Anthropic key, one runs Ollama locally. Committing one person's choice makes the other's run wrong.

    It asks before it spends#

    update is the only command that costs money, and tokens have no undo. So it asks first, and the question names what it is about to buy. Without a terminal to ask at it refuses rather than proceeding, unless you passed --yes up front.

    The question also says how many of the items would replace a translation that is already there. From CLI 0.6.0, plan offers a cell again when its English text or its context changed after StringLane translated it, and applying such an item overwrites what the cell holds. A cell somebody has since re-translated by hand is left alone. With --yes, the report says the same number after the write, and --json carries it as retranslatedCount.

    Do not put --yes update in a CI job. A pipeline that translates on its own is a pipeline that commits work nobody read.

    Narrowing the work#

    stringlane update . --target de,fr

    Only those locales are planned and translated, which is the cheap way to try it before running it across everything.

    How many requests run at once#

    stringlane update . --parallelism 4

    update keeps two model calls in flight by default. --parallelism takes a whole number from 1 to 8; raise it if your provider plan allows more requests per minute. STRINGLANE_AI_PARALLELISM sets the same value for every run, and the flag wins over it. Any other value, such as 0, 9 or 2.5, exits 2 before any credential is read or any request is made: it is never quietly clamped.

    Keeping a record#

    stringlane update . --out-dir ./l10n-audit

    Writes the plan and the candidates it used alongside the run, so a translation you disagree with later can be traced to the exact input it was made from. Your key does not appear in any of it: there is a test that runs the shipped binary as a separate process with secrets in its environment and searches every byte of everything it produced.

    When a run half-succeeds#

    The write itself is all or nothing, so a failure part-way through leaves your files exactly as they were. What can happen is that the model returns fewer usable translations than were planned: some keys come back valid, others fail validation.

    Each answer is checked on its own. One that drops a placeholder, breaks a plural branch or names a placeholder the key does not have is left untranslated, and every other translation in the run is still written.

    You are told which keys are still missing, by name, rather than being given a success message that quietly covers a partial result. Re-running plans afresh from the current state of the files, so it picks up exactly what is still outstanding and does not re-buy the work that already landed.

    Frequently asked questions

    Where does stringlane update read my API key from?
    From environment variables only. It is not read from stringlane.yaml, there is no config file for it, and it is never written to a keychain, a log, a report, a JSON envelope or an audit artifact.
    Can I use a local model instead of a cloud provider?
    Yes. Set STRINGLANE_AI_BASE_URL to your runner and pass --provider local with the model name it has pulled. LM Studio and Ollama need no key, and nothing leaves your machine.
    Does stringlane update skip the validation the rest of the CLI does?
    No. It is the same gate with the plan and the candidates kept in memory instead of on disk. Every translation is checked against the same rules stringlane check applies. A model answer that breaks a placeholder or a plural is left out and its key is named, and the translations that pass are written all or nothing.
    How many AI requests does stringlane update send at once?
    Two by default. Pass --parallelism with a whole number from 1 to 8, or set STRINGLANE_AI_PARALLELISM, to change it; the flag wins over the variable. Any other value exits 2 before a credential is read or a request is made.

    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