Assisted mode: a coding agent driving the CLI
When a coding agent such as Claude Code, Codex, or Cursor runs varlatch
commands for you, it uses your own credential, and everything a command
prints goes into what the agent reads. Assisted mode keeps Secret values out
of that output by accident-proofing the commands an agent uses:
varlatch runmasks Secrets in the command’s output by default, and refuses to start when it cannot mask one.values setandvalues rotatenever take a Secret’s value from the command line, and never prompt.values deletedeletes only an item named again with--confirm.member removeandmember leaveact only on a person or organization named again with--confirm.project deleteandorg deleteact only on a Project or Organization named again with--confirm, and so does approving an Organization’s deletion.loginwith no sign-in method starts a device sign-in that the human approves in a browser, instead of waiting for a browser on this machine.
Assisted mode changes only what the CLI does on your machine. It never
changes what you are allowed to do. The server sees it only in the CLI’s
User-Agent, varlatch-cli/<version> (<platform>; <arch>; assisted), and
the audit log records it as the client of each event the command causes,
such as varlatch CLI 0.16.0 on Linux, assisted, next to your name and
the credential used. That is what the CLI says about itself, not proof: it
tells you a coding agent was driving the CLI, but a coding agent that drops
--assisted and sets none of the markers below is recorded as you.
Turning it on
Section titled “Turning it on”varlatch --assisted <command> [args...]--assistedis the documented form. Put it in every command: many coding agents start a fresh shell for each command, so an exported variable does not carry over. The option may appear anywhere before a--, and it works in every shell, including PowerShell. The Varlatch skill, whichvarlatch initandvarlatch agents installput where coding agents look, tells them to.VARLATCH_ASSISTED=1turns it on too, for tools that can set the environment of every shell an agent starts.- Coding agents’ own markers are a backstop. The CLI also enters
assisted mode when it sees one of the variables coding agents set in their
shells:
CLAUDECODE,CODEX_THREAD_ID,CURSOR_AGENT,COPILOT_CLI,COPILOT_AGENT,GEMINI_CLI,OPENCODE,AGENT, orAI_AGENT(set, and not empty or0). A coding agent that sets none of them is protected only while it passes--assisted. VARLATCH_ASSISTED=0turns marker detection off, for example when an unrelated tool setsAGENTin your shell. It never overrides an explicit--assisted.
varlatch run
Section titled “varlatch run”-
Output is masked by default. The command’s stdout and stderr go through output redaction, as with
--redact, even when your output is a terminal: the command then writes to pipes instead of the terminal, which a coding agent captures anyway. -
Inherited Secrets are masked too. Besides the Secrets delivered in the run, the filter holds the value of every name the command inherits from your shell that Varlatch knows to be a Secret: a Secret stored in the environment (including one withheld from you), or an item the active Contract marks sensitive. Reading the Contract needs
contract.read; without it, only stored Secret names count, and the run says so. Nothing is fetched to build the filter. -
Before the command starts, the run says (on stderr) when no values are stored in Varlatch for the environment (the command still gets what it inherits), and when a
.envfile exists in the project that the run does not read, with the value-free command to compare its names. Only the file’s existence is checked, never its content: it may hold values already stored, or older copies. -
A Secret too short to mask stops the run. Values shorter than 8 bytes cannot be masked (masking them would corrupt unrelated output, and the masks would give the value away). The run names those items and exits with status 78 before the command starts. For
run -e production:varlatch: this Secret is shorter than 8 bytes, so its value cannot be masked in the command's output: PINLeave PIN out only if the command's code or documentation shows that the command does not use it (no approval needed):varlatch --assisted run -e production --omit PIN -- <command>Then name PIN left out in your answer, and say whether the task itself was done: getting past this refusal does not show that the command did what was asked.If you are not sure, or the command uses PIN, stop and ask the human what to do about PIN. Approval for one item or action never covers another.- Only if they approve replacing PIN with a new random value (it overwrites the current one):varlatch --assisted values set PIN -e production --replace PIN --generate hex:32A credential a provider issued is never generated: the human enters it, in their own terminal: varlatch values set PIN -e production- Only if they approve marking PIN as not secret (a Contract change, for the whole project): varlatch --assisted agents guide contract- Showing it unmasked is the human's alone, in their own terminal (assisted mode refuses it; every other Secret stays masked):varlatch run -e production --allow-unmasked PIN -- <command>Nothing was started.The agent may leave the item out with
--omitand run again only when the command’s code or documentation shows that the command does not use it. That needs nobody’s approval: the command then never gets the value, so nothing passes unmasked. Its answer must then name every item it left out and say whether the task itself was done: getting past exit 78 does not show that the command did what was asked (a command that runs without an item it needs may fail, or seem to work and do the wrong thing), and the run reminds it on stderr. When the agent is not sure, it does not leave the item out: it stops and asks. Each other remedy is the human’s decision, for the named item (and environment) only. After that approval, a safe remedy is the agent’s own command, with--assisted: a new random value replaces the item with--replacenaming it. A credential a provider issued is the human’s to enter, in their own terminal, and showing a Secret unmasked stays the human’s alone. Every command names the refused run’s environment (always, even when it came from the default), its server when the run overrode it (--serverorVARLATCH_SERVER), and for the human’s retry its--strict,--allow-inherited,--export-context,--omit, and earlier--allow-unmaskedoptions. -
--omit <NAME>leaves an item out of the run (repeatable, in every mode, not only in assisted mode). The command does not get it: Varlatch does not deliver it, and removes a copy the command would inherit from your shell under that name. In a default run an omitted Secret is not fetched at all. The check for values too short to mask covers only what the command gets, so a short Secret left out no longer stops the run; every other Secret is masked as before. The name must be an item stored in the environment or in its Contract: any other name exits with status 64 before any Secret is disclosed.--omitcannot name an item that--allow-unmaskedor--allow-inheritedalso names. Before the command starts, the run says on stderr what it left out. A Secret left out is not masked if the command reads it some other way (from a provider’s own settings, for example): the run never fetches a value only to mask it. With--strict,--export-context, and--redact, see strict startup, type generation, and output redaction. -
Marking an item as not secret changes the Contract, for every environment of the project: show the active revision (
contract show), write itscontractfield to a file in a new temporary directory, change only that item’ssensitive, push the file (contract push --file <contract.json> --json), and activate the returned revision. When the refused run overrode the server, the message says so (add --server <url> to every contract command): every contract command needs it, or it changes the default server’s Contract. The coding-agent guide prints the steps:varlatch agents guide contract. -
The CLI cannot tell a human from a coding agent that leaves out
--assistedin a shell without a marker. A command printed for the human’s own terminal is theirs; the instructions tell agents never to run one. This is guidance, not an enforced boundary. -
--allow-unmaskedand--no-redactare refused in assisted mode (status 64, nothing started): showing a Secret is the human’s decision. The refusal prints the human’s override for their own terminal, with the same environment, server, and startup options (--strict,--allow-inherited,--export-context), so the override never weakens the run’s policy. -
The human’s override, outside assisted mode:
varlatch run --allow-unmasked <NAME> -- <command>(repeatable) lets the named short Secrets through unmasked in that run, and keeps everything else assisted mode protects: every other known Secret, inherited ones included, stays masked, and another Secret too short to mask still stops the run. It is not an unmasked run, and it cannot be combined with--no-redact. The option is checked strictly, in every mode, before anything is fetched: each--allow-unmaskedneeds an item’s name after it, and the--allow-unmasked=<NAME>spelling is not supported. A malformed form, or a misspelled option such as--allow-unmask, exits with status 64 and starts nothing; it never falls back to a run without masking. (Every option ofvarlatch runis checked this way; see scripting.) -
To compare a platform’s values with Varlatch’s, do not print the environment through
varlatch run: every Secret is masked, so each one would look different.varlatch sync checkcompares inside Varlatch and prints one status per key, never a value, so assisted mode allows it, a Secret too short to mask included. -
These are protections against accidents, not a boundary: an agent that deliberately turns assisted mode off is outside what they cover.
-
--agent-saferuns are unchanged: the Agent holds Placeholders, not Secrets, and redaction does not apply there. See Agent-safe runs.
values set and values rotate
Section titled “values set and values rotate”- A Secret’s value on the command line is refused with status 64, and
nothing is stored. An item counts as a Secret when the active Contract marks it
sensitive, when it is not in the Contract, or when the Contract cannot be
read. The refusal names the safe forms below, and suggests asking the
human to run
varlatch values set <ITEM> -e <environment>in their own terminal, or to use the dashboard. Non-sensitive items are unaffected. - There is no prompt when no value is given: a coding agent cannot type into one. The refusal gives the same command for the human.
- Every command a refusal suggests names the environment the agent’s
command resolved (
-e), so a handed-over command targets the same environment. The human’s command has no--assisted, so it prompts without showing the value. - Replacing an existing value needs
--replace <ITEM>(status 78 otherwise, nothing stored). The command line is checked first, including the value source (one only) and the--generateform, and a missing value (assisted mode never prompts): any of these is status 64, with no request. The existence check comes next, before any value is read from a file or standard input, prompted for, generated, or written. A value the environment inherits from its parent environment counts as existing: setting the item in the child overrides it, which changes what the child uses. When the server cannot say whether the item has a value (denied, for instance), it counts as existing.--replacemust name the item the command sets or rotates; approval for one item never covers another. It records the override’s intent: it is not proof that a human approved, nor an authentication or a permission. Outside assisted mode,values setandvalues rotatereplace as before.
values delete
Section titled “values delete”varlatch --assisted values delete <ITEM> [-e <environment>] --confirm <ITEM>- Every deletion needs
--confirm <ITEM>in assisted mode, for a plain value and a Secret alike (status 78 otherwise, with no request and nothing deleted). Nothing is inferred from whether the item has a value or how the Contract classifies it. --confirmmust name the item the command deletes; another name is status 64. Approval for one item never covers another.- It records the deletion’s intent. It is not proof that a human approved, nor an authentication or a permission. A coding agent adds it only after the human approved deleting that item in that environment.
- The refusal names the environment, and gives the human’s command for their own terminal, with the environment and an overridden server.
- The command line is checked strictly, in every mode, before any
request: an unknown option (
--env), an option without its value, an option given twice, or an extra argument is status 64. Outside assisted mode a deletion needs no--confirm, as before. - The MCP server’s
varlatch_delete_valuetool has the same rule: see MCP.
member remove and member leave
Section titled “member remove and member leave”varlatch --assisted member remove <member> --confirm <member>varlatch --assisted member leave --confirm <organization>- Removing a person or leaving an organization always needs
--confirm, naming the person (as given) or the organization again, in every mode. In assisted mode, without it, the command refuses with status 78 and gives the human’s command for their own terminal; outside assisted mode it is status 64. Either way nothing is sent and nothing changes. --confirmmust name the same person or organization; another name is status 64. Approval for one never covers another.- It records the decision’s intent. It is not proof that a human approved, nor a permission: removing someone still needs the built-in admin role in the organization. A coding agent adds it only after the human approved removing that person, or leaving that organization.
member listandmember roleneed no--confirm.
project delete and org delete
Section titled “project delete and org delete”varlatch --assisted project delete <slug> --confirm <slug>varlatch --assisted org delete <slug> --confirm <slug> [--after <days>]varlatch --assisted org delete <slug> --approve <request-id> --confirm <slug>varlatch --assisted org delete <slug> --cancel <request-id>- Deleting a Project and scheduling an Organization’s deletion always
need
--confirmwith the exact slug, in every mode. In assisted mode, without it, the command refuses with status 78 and gives the human’s command for their own terminal; outside assisted mode it is status 64. Either way nothing is sent and nothing changes. - Approving an Organization’s deletion needs
--confirmin assisted mode, because the approval lets the deletion run. Outside assisted mode, the request ID names what is approved. - Cancelling needs no
--confirm: a cancel undoes a scheduled deletion, and--confirmwith--cancelis status 64. --confirmmust name the same slug; another one is status 64. Approval for one never covers another.- It records the decision’s intent. It is not proof that a human
approved, nor a permission: deleting a Project needs
project.manage, and an Organization’s deletion the built-in admin role. A coding agent adds it only after the human approved deleting that Project or Organization. - The command line is checked strictly, in every mode, before any
request:
--after,--approveand--cancelcannot be combined, and--aftertakes 1 to 30 days. org deletionshows the open request and needs no--confirm. The MCP server has no tool for either deletion.
Changes that need your approval
Section titled “Changes that need your approval”varlatch --assisted security set admin-step-up offvarlatch --assisted --approval <id> security set admin-step-up offSome changes need the person’s approval with a trusted passkey, such as
turning an organization’s security control down or
off. Unlike --confirm, this is proof: the server makes the change only
after you approved that exact change in a browser with your passkey.
- The CLI never waits in assisted mode. It prints what the change does (the server’s summary), the approval address and its expiry on stderr, tells the agent to stop and show you the address, prints the command to run again, and exits 75. Nothing has changed yet.
- You approve it yourself, in a browser where you are signed in, with a trusted passkey and its PIN, fingerprint or face. The agent must never open or approve it for you, and cannot: an approval needs your passkey.
- Then the agent runs the printed command: the same command with
--approval <id>. The CLI checks that the approval is approved and sends the change with it. An approval covers that one change and is used once; it expires 10 minutes after the CLI asked for it. - The output never contains a secret value.
Signing in
Section titled “Signing in”varlatch --assisted login --server <url> --startvarlatch --assisted login --server <url> --wait [--timeout <seconds>]A coding agent cannot wait for a browser sign-in on your machine: its shell commands time out, and the browser may be elsewhere. Device sign-in splits sign-in into two short commands:
--startprints an address and a code, and exits. In assisted mode,loginwith no sign-in method does this. The agent gives you both; you open the address in a browser on any device, sign in with your passkey, enter the code, check who asks (the address and client that started it, and how long the credential lasts), and approve with your passkey again, or deny. The code lasts 10 minutes.--waitcollects the credential once you approved it, stores it like every login, and exits 0. Still waiting for your approval after 60 seconds (--timeout, at most 600), it exits 75 and keeps the sign-in for the next--wait. Denied, expired, or already collected: 77, and nothing is stored. The skill tells the agent to run--waitonly after you say you approved.- The sign-in’s private code never appears in output: the CLI keeps it
in
pending-sign-ins.jsonin its configuration directory, readable only by you. Device sign-in runs only over HTTPS, or to a loopback address in local development, and follows no redirect. - Approving signs that CLI in as you, with your access. Approve only a sign-in you started yourself, or one your coding agent started for you just now; a code someone sends you is a phishing attempt.
--token-stdin,--token, and--oidcwork as before in assisted mode.- Inside an agent-safe run there is no sign-in: every
loginexits 64 before sending anything. The run’s read access comes from--agent-metadata.
Giving a value without the command line
Section titled “Giving a value without the command line”These work in every mode, and keep the value out of shell history, process lists, and anything that records the command.
varlatch values set API_KEY --generate hex:32 # a new random value, never shownvarlatch values set TLS_KEY --from-file key.pem # a file's contentop read op://vault/item/key | varlatch values set API_KEY --stdinvarlatch values set API_KEY # in a terminal: a hidden promptvarlatch values rotate API_KEY --stdin --grace 3600 < new-key.txtop read op://vault/varlatch/token | varlatch login --server https://varlatch.example.com --token-stdin--generate <encoding>:<size>creates the value from the operating system’s secure random source:hex:<bytes>,base64:<bytes>,base64url:<bytes>(16 to 4096 random bytes), oralnum:<characters>(22 to 4096 letters and digits). The output says which generator was used, never the value.--stdinand--from-fileremove one trailing line break, whichechoand most editors add. The value must be UTF-8 text without NUL bytes, and not empty.--stdinrefuses a terminal; leave the value out for a hidden prompt instead.- The hidden prompt shows nothing as you type. Backspace removes the last whole character (an emoji or an accented letter included), and arrow and function keys are ignored rather than stored.
login --token-stdinreads a credential the same way, removing one trailing line break; it refuses a terminal, an empty credential, and one with whitespace in it. Sign-in stays the human’s step: in a terminal,varlatch login --server <url>signs in in the browser.- Give the value one way only. Two sources are refused. A value that is not well-formed Unicode text is refused from every source.
- The command line is checked strictly, in every mode, before anything
is read, prompted for, or written. An unknown option (
--env, or--environment=production, which is not supported), an option without its value, an option given twice (-eand--environmentcount as one), or an extra argument exits with status 64 and stores nothing. A typo can never become the stored value. A value that begins with-goes after--:varlatch values set OFFSET -- -1.--grace(rotate only) takes a whole number of seconds.
Limits
Section titled “Limits”Assisted mode protects against accidents. It is not a boundary: a coding agent runs as your operating-system user, and your approval of its actions is the control against deliberate misuse.
- It covers the values Varlatch delivers or knows by name. A secret already in the agent’s environment under a name Varlatch does not know passes through.
- Masking recognises the value as written and the encodings listed in output redaction. Hex, other escapings, compressed output, and values the command derives or deliberately encodes are not masked.
- A coding agent that sets no marker and leaves out
--assistedgets the default behaviour.

