Batawn connects the Claude Code and Codex sessions your team is already running, so the honest version of this page matters more than a reassuring one — and the honest version changed when the agents moved onto your machines. Below is what we hold, what we do not, what other people in your room can reach, and what we have not built yet.
Where the model runs
We never front inference, and we hold no model key
Your agents run in your own Claude Code or Codex, on your own machine and your own subscription. There is no model key to give us, so there is none to encrypt, none to leak and none for us to lose. Batawn holds no inference account and there is no model API key in this application's environment — it refuses to start if one is there. Other secrets we do hold: the GitHub App's own credentials, and for a team using shared connections the provider's tokens. Both are encrypted with AES-256-GCM.
Your machine runs the code, not ours
Batawn no longer runs a sandbox, a container or a virtual machine for you. The tools run where you are sitting, under Claude Code's own permission prompts, against your own checkout.
What other people in your room can do
This is the part to read twice
Because your agent runs on your machine, somebody else in your room can affect what happens on it. That is the feature. It is also the thing to understand before you invite anyone: this is a tool for people who already work together, not a public room.
Pausing is free. Steering asks.
Anyone in the room can pause your agent without your permission, and pausing interrupts the tool it is running the way pressing escape in that terminal would; unpausing carries the same turn on. A pause lands at the next tool call, so an agent that is writing rather than running something is not interrupted until it reaches for one. On Codex only the commands Batawn started are interrupted, never the Codex process itself. Sending it an instruction is different — it arrives as a question, your agent asks you before acting on it, and the host's own tool permissions still apply underneath.
Nobody gets in without being let in
An invite code alone gets somebody nowhere. They ask to join under a name, and the room's owner approves or rejects them — nobody else in the room can, however long they have been in it. The owner can remove anyone at any time, which stops their agents and frees whatever files those were holding.
You cannot put an agent on somebody else's machine
An agent is always spawned by, and runs on, the machine that created it. There is no way to start one on a teammate's laptop, and no way to report work as an agent that is not yours.
Your code
What we store
Several things, all of which are your source code and all of which we would rather you knew about than discovered:
The room's log. Every prompt typed at a terminal in the room, every tool call an agent makes with the arguments it passed — the text written to a file, the command run in a shell — and every reply the agent gives. None of that is truncated. What a tool prints back is kept as a preview of the first 400 characters. This is what makes a room replayable, reviewable and forkable, and it is the product.
Finished work. When an agent completes a task it attaches the diff of what changed, up to 200,000 characters, with its summary. That diff stays with the task.
The working tree it reported last. A terminal keeps the room's repository row up to date: the branch, the commit it started from, and the current uncommitted diff, up to 120,000 characters, overwritten as the work goes on. It is how the room shows what is in flight.
Shared context. Repository instructions and uploaded text files are stored so later agents can receive them. A file attached from the repository is stored as its path, immutable Git blob identifier, size, and content hash; the file body is read from that exact version in an agent's checkout. Task attachments stay with the task as part of its record.
What we do not store
No complete copy of your repository, and no disk image. Agents run against your checkout on your machine. Batawn stores the git state and narrowly selected shared-context records described above, not a repository clone.
How long
For as long as the room exists. Closing a room revokes access for everyone but deliberately keeps the record for its owner — that is the difference between closing and deleting. Repository context remains available to rooms on that team and repository until a member removes it or the team is deleted. Task context is preserved with completed task history and cannot be edited after work starts. Deleting a room is not self-serve yet: ask us and we will do it. We would rather say that than imply a button exists.
Analytics never see it
We use product analytics with session replay, and two mechanisms keep your content out of them. The elements that render it — the workspace pane, diffs, terminal output, file trees, the composer, your room list — are marked so the recorder masks them. And every payload is walked before it leaves: the text an element displayed is dropped, its attributes are dropped, and an address of ours is cut down to the shape of the route with its query and fragment removed. An address we do not recognise as one of our routes is treated as yours and redacted. Error reports go through the same scrubbing, in the browser and on the server.
Who can read a room
Deny by default
Every room-scoped table has row-level security, and every policy is keyed on being a participant in that room. It is enforced by the database rather than by application code, so a bug in a page cannot widen it. The public home page proves it on every load: it queries rooms with no session and must get zero rows.
A guest sees the conversation, and two things beyond it
Someone invited as a guest can read the room and answer questions but cannot open the workspace: tool calls, tool results, file changes and anything a terminal wrote are filtered out of the log for them by a database policy, not a hidden button. Two things are not behind that policy, and you should assume a guest can read them: the diff attached to a task that has been completed, and a room export, which carries the prompts people typed at their terminals and the agents' replies. Both ask only whether you are in the room. Invite a guest on that basis.
Closing means closing
Closing a room removes every participant except its owners, revokes every live invite link, and stops the agents. No new agent can be started in it and no fresh link can be minted for it. This is why rooms have their own links rather than one permanent per-project URL.
Only one room can ever be public
A room can be published as a public recording, by its owner, after being told exactly what that discloses. At most one room in the whole system can be public at a time, enforced by a unique index.
Your repository
GitHub access
Batawn connects through a GitHub App you install, on the repositories you choose. For that App we store the installation, not a personal access token. Connecting GitHub as a shared connection is a different thing and does store a token: a GitHub user token carrying repo scope, encrypted here, which acts as the owner who connected it. While you are in a room, your terminal can mint a token for that room's repository alone — contents only, never stored on our side, and kept on your own machine until it expires. It is an ordinary git credential: it can write to any branch of that repository, including the default one, and a room can be pointed at the default branch. Batawn opens no pull request for you; a person does that. The only thing the plugin pushes by itself is a handover: unfinished work for a task you hand over is parked on a refs/floor/wip/<task> ref so the next person has the bytes.
Shared connections
A team owner can connect Supabase, GitHub, PostHog, Resend or Stripe once and let chosen rooms use it. It is being turned on team by team, so your team may not have it yet.
Nobody else signs in to the provider
People in a room never sign in to the provider, and nothing is configured on their machines. Their agents ask Batawn, and Batawn's server makes the call. That is the point of it: one connection for the team instead of a token on every laptop.
Every action runs as the connected account
Actions run as the provider account the team owner connected, with whatever that account may do at the provider. The provider's own logs show that account, not the teammate whose agent asked; Batawn's history records who asked, who decided and what happened.
The credential stays on our server
The provider's tokens are encrypted with AES-256-GCM under keys held only in the server's environment, and each is bound to the connection it belongs to, so a copied value opens nowhere else. A database read alone does not recover them. They are not sent to browsers, terminals, agents, the room's log, product analytics or error reports. Disconnecting deletes the stored credential and asks the provider to revoke it where the provider supports that; where it does not, remove Batawn's access in the provider's own settings as well.
An owner approves one exact request
By default every action waits for an owner of the room, who sees the action, the target, the environment and the arguments, with sensitive values hidden. Approving runs exactly that request, once; different arguments are a new request needing a new approval. Only the agent that asked waits. A denied, expired or revoked request releases it and puts a manual follow-up on the room's task list.
Auto-approve is a real decision
A room owner can let actions run without approving each one. The agents of that room's owners and members can then run whatever the room allows — production changes included, if those are allowed — with nobody looking first. Guests and observers are refused whatever the mode. Room membership and the actions, targets and environments the room allows still apply, and nothing outside them runs: auto-approve removes the per-action check, not those limits.
Who gets nothing
Only owners and members who have been let into the room can make requests or see its connections. Guests and observers do not see the requests, the decisions or the results, and neither does anyone holding an invite that has not been accepted or watching a public replay. One thing does reach them: when an action is denied, expires or fails, the manual follow-up it leaves on the task list is an ordinary task, and anyone in the room can read it — including the provider, the action, the target, the environment and the arguments it would have used.
Taking access away is immediate
Removing a person or an agent, turning a connection off in a room, narrowing what it allows, disconnecting it or closing the room ends that access at once: waiting and approved requests are cancelled and cannot start. An action a provider has already begun cannot be called back by Batawn — it runs to its end, and the history records that it started before access was removed.
What we cannot promise
Batawn cannot undo an action once a provider has carried it out, and cannot make a provider honour a cancellation. If a provider stops answering after a change was sent, Batawn cannot tell whether it landed: the request is stored as failed, carrying a code that says the outcome is unknown, and the room tells a person to check at the provider before doing it again. Every request, decision, outcome and prevented duplicate is kept in the room's history.
What we do not have yet
Batawn is early and run by a very small team. There is no SOC 2 report, no penetration test to show you, no SAML or SCIM outside an enterprise conversation, no configurable data-retention policy, and no self-serve way to delete a room — that one is a support request today. Shared connections act as the one account a team owner connected, so there is no per-person identity at the provider. If your security review needs any of those, we would rather tell you now than halfway through it.
Found something wrong here, in the writing or in the code? Email support@batawn.com.