docs / security & privacy
What runs where, and what leaves your machine.
Balladeer's terminal client installs on your machine. This page covers what it puts there, what leaves and what never does, who can see what, which model vendors touch your data, how one workspace is kept out of another, and how to leave. The Claude and ChatGPT connector installs nothing.
On your machine
The installer puts a small client on your machine and wires it into how you already work. Concretely:
- The client itself: the
balladeerCLI, installed as one global package. Most coding agents reach your workspace through Balladeer's hosted connector. On a paired machine running Claude Code 2.1.163 or newer, the CLI can also run on demand as a thin transport to that hosted service. It runs only while Claude Code uses the connector; nothing runs resident on your machine. - A connector registration: the Balladeer MCP server entry in your agent's own config, written by the setup commands and pointing at your workspace's server. Claude Code's session-aware form forwards ordinary MCP requests unchanged and owns no local Balladeer tools, graph, storage, model call, or permission decision. Claude Code, Codex, and Cursor each have their own setup command. Other entries in those files are preserved.
- Agent guidance: a conventions file Balladeer owns and keeps current, plus a short marked block in your agent's own config file (Cursor gets a project rule file instead). Your own content outside those markers is never rewritten. Where the markers are ambiguous, setup stops and tells you rather than guessing.
- A status line: one line in your editor showing what awaits your call.
- A pairing credential in
~/.balladeer, created when you approve the device in your browser, stored readable only by you. There is no token to copy and paste. The server keeps only a SHA-256 hash of that credential, so a copy of our database yields nothing that can sign in as you.
What leaves, and what never does
What syncs to your workspace on Balladeer's hosted server:
- Decisions your team records: the claim, the question, the why, the rejected options, and the confirmations, dismissals, and ratings your team applies to them.
- Documents you explicitly upload for seeding at app.balladeer.ai (where seeding is enabled for your workspace), so decisions can be drafted from them for your review. Seeding upload is the only path a document travels to us, and the uploaded file itself is not stored: a PDF, Word, PowerPoint, or Excel file is converted to text in memory, any copy handed to the model that reads it is deleted as soon as conversion finishes, and only the extracted text is kept, as a staged document you can review and remove.
- The questions you ask, so they can be answered against your team's memory. The text of a read is also kept in your workspace's serving log, which is what lets you audit what was served and what your team rated useful.
- A privacy-safe conversation ticket, only where the client can supply one, so decisions can be grouped and recalled without mixing simultaneous sessions. Claude Code's raw session UUID is SHA-256 hashed into a provider-versioned ticket before it leaves your machine; the raw UUID is never sent or stored by Balladeer.
What never leaves your machine:
- Your code and your files. Balladeer is not a code index. Your repository is read by your own agent, on your machine, under your agent's own permissions. Connecting GitHub does not change this: the GitHub App's permissions are read-only pull request, issue, and membership metadata, with no access to repository contents, so the connection cannot read your files. What it reads is pull request and issue text from the repositories you choose at install.
- Your conversations and editor sessions. There is no ambient capture: nothing is recorded unless your agent explicitly records it or you explicitly upload it.
- Documents your agent works with locally. Drop a spec into your Claude Code session, work through it, extract decisions from it: Balladeer never sees or stores that document. Only the decisions your agent explicitly records arrive, each one visible in your review surfaces, and none of them carries the document along.
Text on its way into your workspace passes a scrubber that redacts common secret formats (API keys, tokens, private keys) before anything is stored, embedded, or sent to a model. It is pattern-based and best-effort, so treat it as a safety net rather than a guarantee: a credential in an unusual shape can still get through.
Who can see what
A decision is visible to your whole workspace by default. It can instead be private to the person who recorded it, or restricted to named people. Restriction fails closed: to anyone outside the audience, a restricted decision is indistinguishable from one that does not exist.
That holds for more than the decision itself. The counts on your status line are filtered, because a count that moves when a hidden decision is added is itself a disclosure. Links are filtered too: relating two decisions requires that you can see both, so the relationship verbs cannot be used to test whether a hidden decision exists.
How one workspace is kept out of another
Balladeer is multi-tenant, and the separation is enforced by the database rather than by application code remembering to filter. Every table that holds your content carries your workspace id and runs under Postgres row-level security, forced on, with a policy that admits only the workspace the current request belongs to. The application connects as a least-privilege role that cannot bypass those policies, and the workspace identity is set per transaction, so a pooled connection can never carry one tenant's identity into the next request.
A short list of infrastructure tables sits outside that scheme, because they are read before a workspace identity exists (the accounts, memberships, and device records that establish who you are) or because they have no tenant dimension at all. None of them holds decision content, and a test fails the build if a new table appears in neither club.
Which models and vendors touch your data
Two vendors process workspace content today, and they are separate answers.
- Anthropic runs the reasoning: seeding extraction, judging, and answering questions. That includes the agent Balladeer runs to compose a Brief. Your workspace can bring its own Anthropic key. When your workspace has supplied one, Brief composition and the other Anthropic calls run on that key. If it stops working, that processing pauses and waits for a new one rather than silently falling back to ours. Balladeer's platform key is used only for a workspace that has never supplied its own. Bring-your-own-key supports the Anthropic family only; if a model outside it were ever configured for a workspace with its own key, the work would be refused rather than run on our credentials.
- Voyage AI computes the embeddings that make retrieval work, and this is the part worth reading closely: embeddings always run on Balladeer's key, including for workspaces that bring their own. What is sent is the text being indexed or searched: a decision's claim, question, rationale, and the systems it touches; the text of evidence your agent attached; and the query text of each read. Bringing your own key changes who pays for and controls the Anthropic calls. It does not remove the embedding vendor.
Where your secrets are kept
Credentials you entrust to Balladeer are encrypted at rest with AES-256-GCM under a master key that lives only in deploy secrets, so the database and its backups never hold a usable key. That covers your workspace's model key and the token for a connected Slack workspace. Each sealed value is bound to the row it belongs to, so a ciphertext moved to another workspace's row fails to open rather than decrypting into the wrong tenant. If a value cannot be sealed, it is refused rather than stored in the clear.
Connected apps
- GitHub (optional) reads pull request and issue text from the repositories you choose at install, so merged work can check off a decision's definition of done. The grant is read-only and excludes repository contents. Disconnecting revokes our access; the app installation itself stays on GitHub until you remove it there.
- Slack (optional, installed by a workspace admin) posts to your workspace and reads direct messages sent to the Balladeer bot, which is how a reply becomes a recorded verdict. It reads workspace member emails to bind a Slack user to the right Balladeer seat. It holds no access to your channels.
- An integration broker handles the OAuth for GitHub and Slack ingestion and holds those provider tokens, so we store only an opaque connection reference. Content fetched from those providers passes through it.
- Authentication is handled by WorkOS, which holds your name, email, and workspace membership. No decision content reaches it.
Our own operational alerts carry workspace names and aggregate numbers (volumes, error rates, spend). They never carry decision content.
What we keep to ourselves
What Balladeer returns to your team is what your team wrote, its standing, and human-readable receipts (which merged PRs cite a decision, how recently it was load-bearing). The machinery underneath (retrieval scoring, ranking signals, the pipeline's internal bookkeeping) is not part of any customer-facing payload, so your tooling can't come to depend on internals that change.
What Balladeer does not do
- It does not mine your history uninvited. Decisions are authored by your agents in the flow of work, or extracted from documents you explicitly seed and then review.
- It does not listen to your meetings or your code review. Someone can tell an agent a decision that got made elsewhere and have it recorded; there is no ambient capture of conversations.
- It does not treat an uploaded document as instructions. Text inside a document you seed is handled as content to transcribe, not as directions to follow, so a document cannot talk the extractor into doing something else.
- It does not show you a mystery score. What your team sees is what your team wrote, its standing, and its receipts; the machinery underneath stays internal, as described above.
Leaving
Two different things, so they are worth separating.
Your machine: balladeer uninstall removes everything setup
installed. It unwires the agent config and status line, removes the client, and moves your
local data directory to a timestamped backup rather than deleting it. Destructive removal
exists but asks you first, and the backup is the default, so leaving never costs your team
the record.
Your hosted workspace: uninstalling touches your machine only and removes nothing from the server. Erasing a workspace's hosted data is not self-serve today; email us and we do it. There is no automatic deletion timer, so a workspace you stop using stays as you left it until you ask us to remove it.
Verified from live product as of 4 Aug 2026.