Your terms are the primary control
Everything you upload, anonymized or raw, is handled under the Terms of Service and the Privacy Policy you accepted at sign-up. Those terms, not a local scrub, govern how your data is processed. Local anonymization is optional, extra protection on top of those terms. It is not the only control.What leaves your machine
Your data leaves your machine only through the SDK’s upload commands, which run locally:
The SDK reads your data sources with your credentials on your machine. Those credentials (your observability platform key, your database connection) never leave it. The plugin itself never scrubs or uploads bytes; the SDK owns the upload end to end.
While a simulation runs, each conversation is also sent to the Plurai backend so it can play the simulated user and score the result: the user’s messages, your agent’s replies, its tool calls and what they returned.
No telemetry. Neither the plugin nor the SDK sends anything about how you use them. Support sees only what you choose to paste, such as the output of
plurai diagnose. Two things stay local or are minimal: once a day the plugin checks GitHub’s public tag list for a newer release, sending nothing about you or your project (turn it off with PLURAI_NO_UPDATE_NOTICE=1), and install failures are logged locally in ~/.plurai/support_refs.jsonl, which is never sent (turn it off with PLURAI_NO_SUPPORT_REFS=1).
The agent descriptions (
plurai.config.yaml, simulation_prd.md, scenario_variables.yaml) are sent as written, in both postures. They describe your agent’s code and tools; anonymization does not scrub them. The same holds for a knowledge base’s domain description.Anonymization posture
Each Environment declares its anonymization posture once, with the top-levelanonymize key in plurai.config.yaml. /simulate asks at the start. When you run stages yourself, the first command that uploads data asks. Either way, your answer is written there.
- Raw (default)
- Anonymized
anonymize: false, or the key absent.Data is uploaded as-is. Every upload prints a RAW (anonymization off) banner, so you always know. The upload is governed by the Terms of Service and the Privacy Policy./trace-to-scenarios refuses to run under the anonymized posture.
How an upload is packaged
Every upload follows the same steps:1
Build one archive
The SDK bundles the data into a compressed archive. The archive is deterministic: the same input always gives the same bytes and the same checksum.
2
Disclose
Before any request that carries content, the SDK prints a disclosure preview to the terminal: what is being sent, its size, its checksum, the posture, and under anonymization a scrub summary. It also writes it to
.plurai/uploads/disclosure-<kind>.txt.3
Record
It appends an entry to
.plurai/uploads/audit.log.4
Upload
It sends the archive. If the backend already holds identical bytes, nothing is sent. If the bytes change after the disclosure, the upload aborts.
The audit log
<your-project>/.plurai/uploads/audit.log is the authoritative record of what left your machine and under which posture, for both postures. When you need to answer “what exactly did Plurai receive?”, read this file.
.plurai/ holds runtime state: the audit log, upload previews, and the anonymization key. Add .plurai/ to your project’s .gitignore so none of it is committed.
Your consent
- Uploads. Each upload is a shell command. In your coding agent’s default permission mode you approve each one. Under
/simulateor auto mode they run without a prompt, but the SDK still prints a disclosure first and logs every upload in.plurai/uploads/audit.log. See Permissions. - Harness edits. When the suite’s quality loop finds a fix for
simulate.py(or the runner declared inharness.entry_wrapper), it asks you first. For runs where nobody can answer, such as CI, setapprove_harness_edits: trueto approve those fixes in advance. Leave it out to keep them unapplied and reported. The plugin never writes this key for you. - Your agent’s code. No command edits your agent’s source.
/simulation-fixesproposes fixes; you apply them.
What the Report withholds under anonymization
On Claude Code, the Report is published as a private Artifact page. On Copilot CLI and Codex CLI, it is a local file you open in your browser. Underanonymize: true, no customer text ships in the Report. It keeps structure, ids, counts, verdicts and eval names, and marks each withheld value as [withheld]:
- Conversation turns, and every quote a judge or a finding took from them.
- Judges’ reasoning and the explanation of each finding.
- The seeded agent context, and the text the Suite wrote for each Scenario: its summary, pass criteria, starting data and the Persona’s background, style and sample dialogue. A Persona keeps only its name.
- The seeded and final world state, which keep only the kind of each record.
- Every tool call’s arguments and responses.
- Evidence, quotes and excerpts in findings, eval descriptions and provenance quotes.
- Knowledge base text: each chunk keeps only its document name and index.
Your login
When you sign in with your browser, the SDK creates its own key and saves it privately on your machine (~/.plurai/credentials.json, readable only by you). The key is never shown, typed or copied into chat. It goes only to the Plurai backend it was issued for, and the plugin hands it only to the installed SDK. plurai logout revokes it. See Environment variables.
Next steps
Environment variables
Connect to the backend and set the sandbox.
Configuration
Set
anonymize and approve_harness_edits.