A coding agent that only runs in one person's terminal is invisible to everyone else on the team. Nobody sees what it was asked, what it read, or what it changed until a commit turns up. Hangar is a chat app where mentioning @claude in a room starts a real Claude Code session on a machine you control. It works in your repo and posts back what it did, and while it runs the room carries a live console of the files it read, the commands it ran and the edits it made.
Two processes, and the split between them is the security model. The server holds the database and cannot execute anything. A companion runs on your own machine next to your repo, holds a bearer token and no database credentials, and is the only thing that ever starts a session. The web app never spawns a process.
How the database stays honest
Every table has row level security forced on. The app role owns nothing and cannot bypass RLS. Policies key on a transaction-local user id that one wrapper sets, so a call site that forgets it returns zero rows instead of everything. Agent messages cannot be forged either: the insert policy only accepts posts bound to whoever is calling, as a user, so the app role cannot write an agent post at all.
The prompt boundary
One module sits between a chat message and a tool call, because the session runs with tool permissions bypassed. Room text is NFKC folded, so a fullwidth bracket cannot survive the ASCII strip. Every Unicode format character is stripped, because bidi overrides make a human's view of a message differ from the model's and that wrecks the audit trail. Then it is fenced and labelled as data.
What is verified
- Schema, RLS and grants applied to Postgres 16 in CI, twice per run.
- 29 tests for the policies and the dispatch queue, against a real database.
- 57 unit tests across the prompt boundary, auth and domain logic.
- 8 end to end tests against the built server, covering the whole flow.
- A term gate that scans the working tree and every object in history, pre-commit and in CI.
A pre-publication audit found 12 real issues out of 56 candidates. The worst one: the roster gated almost nothing, so somebody signed in but not on it could create a room, add themselves, and queue a dispatch.
It is new. The whole flow runs and CI checks it against a real Postgres on every push, but it has not been run in anger. Threads, search, attachments and editing are not built, and no identity provider ships with it: you wire your own.