Who this is for
Engineers deciding whether to run a recorder next to their agent. Security teams reviewing what it stores, what it listens on and what it can send. Procurement and compliance checking where data lives before approving a tool. This page describes what the software does today. The technical security model, with more detail, is in the docs at docs.postrun.app/security.
What Postrun records, and where
Postrun records what a supported coding agent (Claude Code and Cline today) does in a session: your prompts, the agent’s replies, every tool call with its input and output, the commands it runs and what they printed, the files it reads and edits, and timestamps, token counts and cost figures the agent reports.
All of it is stored on your computer under ~/.postrun: raw capture files, the SQLite session store and its write-ahead log, and the ingest token. Everything Postrun creates there is owner-only, with directories set to 0700 and files to 0600. Older files with wider permissions are tightened when Postrun opens them. The capture hook sets umask 077 for the same reason.
The local store is not redacted. It holds whatever the session contained, including the output of commands such as env. Treat ~/.postrun as sensitive. Deleting the folder removes everything Postrun has stored. There is no account and no copy anywhere else.
You can also delete a single session from the review app. Its content is overwritten in the store, not just unlinked, its raw files are removed, and Postrun will not record it again. The agent’s own copy of the session, in Claude Code or Cline, is left for you to delete there.
Network exposure
Postrun runs two local listeners: the review app and API server, and a telemetry receiver that Claude Code reports to.
- Both bind to
127.0.0.1only, so they cannot be reached from other machines on your network. - Both refuse any request whose
Hostheader is not127.0.0.1,localhostor[::1]. This stops DNS rebinding, where a web page points its own domain at 127.0.0.1 to read a local API from your browser. - No CORS headers are ever sent, so other websites cannot read responses from the API.
- The API has one write route,
POST /api/ingest, for adapters that push sessions. It requires a bearer token stored in~/.postrun/ingest-token(mode0600), which a cross-site browser request cannot send. Bodies are capped at 8 MB before and after gzip, and every batch is validated against the session schema before anything is written. - The telemetry receiver caps each request at 32 MB before and after gzip.
- Responses carry
X-Content-Type-Options: nosniff,Referrer-Policy: no-referrerandCache-Control: no-store. Internal error details are logged locally and never returned in a response.
No telemetry
The Postrun app contains no telemetry, analytics or crash reporting, and does not contact our servers. Nothing syncs in the background. A session leaves your machine only when you export it, one session at a time, and you decide where the file goes.
Files it reads and changes
Postrun reads the agents’ own files (Cline’s session folder under ~/.cline, and the events Claude Code’s hooks write) but never writes to them. The only file it edits outside ~/.postrun is ~/.claude/settings.json, so that Claude Code sends telemetry to the local receiver and runs the capture hook. The original is backed up once to ~/.claude/settings.json.postrun-backup, the change is merged in place with every other setting kept, and the write is atomic. Postrun does not ask Claude Code to write raw API request bodies to disk.
What export does
Export turns one session into one HTML file you can share. Redaction is part of every export, not an option. Before the file is written, Postrun masks values and replaces each with [REDACTED:kind]. The kinds are:
private-key: PEM private key blocks (-----BEGIN ... PRIVATE KEY-----)aws-access-key: AWS access key IDs starting AKIA or ASIAgithub-token: GitHub tokens (ghp_, gho_, ghu_, ghs_, ghr_) and fine-grained github_pat_ tokensanthropic-key: Anthropic API keys starting sk-ant-openai-key: OpenAI keys starting sk-, sk-proj- or sk-svcacct-stripe-key: Stripe secret and restricted keys (sk_live_, sk_test_, rk_live_, rk_test_)slack-token: Slack tokens starting xoxa-, xoxb-, xoxp-, xoxo-, xoxs- or xoxr-google-api-key: Google API keys starting AIzajwt: JSON Web Tokens (three base64url parts starting eyJ)url-password: Passwords in URLs, such as postgres://user:password@hostauth-header: Bearer, Basic and Token values in Authorization headerscredential: Any value assigned to a credential-named key (see below)
The credential-name rule
A value is masked as credential when it is assigned to a name that looks like a credential, in forms such as NAME=value, "name": "value" or name: value. A name counts when a whole segment of it, split on _, . or -, is a credential word such as secret, token, password, pwd, passphrase, api_key, private_key, access_key, auth, credentials, client_secret or webhook_secret; or when a camelCase name ends in one, such as apiKey, accessToken or dbPassword. Whole segments keep names like author or tokenizer from matching. The value must be at least 6 characters, and obvious non-secrets such as true, placeholders, and references like ${VAR} or process.env.X are left alone.
Paths, machine details and notes
Home folder paths (/Users/name, /home/name, C:\Users\name) become ~. The export also leaves out the machine name the session was captured on, the local paths of capture files, the owner ID, and any private review note stored with the session.
You see every mask
The exporter lists every masked value with its kind, where it was (for example, step 4, command output) and the text around it, so you can check it before sending. Home paths are counted rather than listed.
The report itself
The exported file contains no JavaScript: steps expand with plain HTML. Every captured string is escaped, and the file carries a Content-Security-Policy of default-src 'none' that blocks scripts, frames, forms and network requests. It uses system fonts and inline styles, so it loads nothing from the internet. Even agent output crafted to look like HTML cannot run in the reader’s browser.
Limits of redaction
Redaction is a safety net, not a guarantee. Skim every report before you share it. In particular, it will not catch:
- Secrets in formats it doesn’t know, assigned to names that don’t look like credentials.
- Credential values shorter than 6 characters, or split across lines.
- Personal data, customer data, proprietary code or business details. It masks secrets, not meaning.
- Usernames in paths outside the standard home folder locations.
Once you send a report, what happens to it is up to the person who receives it.
This website
postrun.app sets no cookies and uses no local storage. Visits and button clicks are counted with Vercel Web Analytics, which is cookieless and shows us only aggregate numbers. If you join the waitlist, we keep your email address. Fonts are served from our own domain and there are no advertising or third-party scripts. The full details are on the privacy page.
Reporting a vulnerability
If you find a security issue in Postrun or this website, email hm@heromomoh.com. Please include steps to reproduce, the version or commit you tested, and the impact you see, and give me a chance to fix it before you disclose it publicly. Postrun is a personal project, so I aim to reply within a few days.
Our contact details are also published at /.well-known/security.txt.