Safety & Privacy
Runlet runs real code against real applications, some of them in production. So it runs nothing you didn't ask for, asks before every run on production, and keeps your code, data, and credentials on your Mac and your own servers. It has no account and no telemetry.
Nothing Runs Until You Ask
Your code runs only when:
- you press Run (or Run Selection, or Profile Run);
- you approve an AI client's request, or allowed its runs on that target for the session (AI Clients);
- you turned on auto-run in a sandbox tab. It never runs on local, Docker, or SSH targets.
Opening a project, a file, or a workspace, switching tabs, and restoring your session never run code. Opening an SQL, Redis, or MongoDB tab, or choosing its connection, doesn't connect or run anything.
The Commands pane boots a project to list its commands only while the pane is open, and never on its own for SSH or production targets.
Production Asks First
Mark a target's environment as production in its project options or profile, and every run asks before it starts:
- The confirmation shows the target, where the code runs, and the code. ⌘Return runs it; Return and Esc cancel, so a reflexive Return never runs code on production.
- Don't ask again for 10 minutes covers snippet runs on that target only. Project commands, shells, and REPLs on production ask every time, and AI clients' runs too.
- The Tests group in the Commands pane is disabled on production, because test suites often reset the database.
- When a run shows that the application says it's in production (Laravel's
APP_ENV, Symfony's kernel, WordPress's environment type) and the target isn't marked, the tab offers Mark as Production. Runlet never changes the marking by itself. - A red badge marks production targets in the toolbar, the tabs, and the status bar, and History keeps a PROD badge on runs made there.
SSH Targets has the details.
Guard Rails for Data and Mail
- Dry Run runs a PHP tab inside database transactions that Runlet always rolls back. It isn't a sandbox: mail (unless intercepted), queues, HTTP calls, and files are real. MySQL and MariaDB schema changes are refused, because they would commit at once, and the transaction holds its locks until the run ends. Production still asks first.
- Mail interception records the mail a run sends without delivering it, where the framework allows it.
- Read-only connections let an SQL tab look at data, production data included, without changing it: the database session is read-only, and Runlet refuses statements that could write before sending them.
Your Code and Data Stay With You
- Code runs where you choose: your Mac, a Docker container, or a server you connect to with your own
ssh. Runlet uploads nothing anywhere else. - Nothing is written into your project or container. Runlet's runner is streamed to PHP on its standard input, and it never runs Composer in your project.
- On a server, your code is never written to disk either. The only things Runlet keeps there are its own runner and the application's compiled PHP, in a private cache that speeds up runs. It's on for new SSH profiles, and one switch in the profile turns it off; Runlet then writes nothing on the server.
- Previews are locked down. Mail and HTML previews run no JavaScript, load nothing from the network unless you allow remote images, and don't navigate.
- Logs stay in the Logs window. Log lines aren't saved, written to the Run Log, or given to AI clients. The Run Log never shows environment values.
- The run inspector stays in its tab. What a run recorded (queries, mail, logs, HTTP requests, jobs, and events) lives in the tab's memory until the next run: it isn't saved in History or your session. See What the Inspector Records.
- Notifications for long runs carry only the run's status, duration, tab title, and target name: never code, output, or errors.
- AI providers get your code only when you ask. Explain or Fix… shows exactly what it would send (the error, the tab's code, and, if you check it, the source where it was thrown), and sends it to the provider you chose only when you click Send. Runlet never runs code a model writes. See AI Assistance.
Your tabs, snippets, history, targets, and settings are in ~/Library/Application Support/Runlet.
What the Inspector Records
The run inspector records what a run did, on your Mac, for the tab that ran it. Its HTTP section sees requests to your APIs, so it handles credentials with care:
- Redacted before they leave PHP:
Authorization,Proxy-Authorization,Cookie,Set-Cookie, API-key and token headers, the password in a URL, and query parameters, form fields, and JSON fields named like secrets (token,key,secret,password,signature, …). The full list is in Credentials Are Redacted. - Bodies are off by default. Include request and response bodies keeps the first 8 KB of each, with secret-named fields redacted, but a body can still hold personal data or a secret Runlet can't recognise. Leave it off on production targets.
- Events are off by default, and their payloads are short summaries, read without calling your code.
- Recording doesn't change your application. The HTTP, Jobs, and Events listeners only listen: they never stop an event, a request, or a job.
You choose what's recorded in Settings ▸ General ▸ Run Inspector. Copy Output as Markdown and Save Output As… include the requests and jobs as one line each, redacted.
What AI Clients Get
AI clients get a run's output: what it printed, dumps, the result, errors, notices, and how it ended. They get nothing from the run inspector: no queries, mail, logs, HTTP requests, jobs, or events. Requests and events can carry data that redaction can't fully cover, so they stay in Runlet's window.
Credentials
- Database passwords of saved connections are kept only in your Mac's Keychain, never in Runlet's files.
- AI providers' API keys are kept only in your Mac's Keychain, shown only masked once saved, and never written into a file, a log, or a message. See Where Keys Are Kept.
- SSH uses your system
sshand~/.ssh/config. Runlet stores no SSH passwords, keys, or passphrases. - AI clients can't see or use saved database connections or their passwords.
- Import from TablePlus, behind a feature flag in Settings ▸ Advanced (off by default), reads TablePlus's connection list only when you click. It copies database passwords only if you tick the box, with macOS asking for each item, and never copies SSH passwords or key passphrases. See Import From TablePlus.
No Account, No Telemetry
Runlet has no account, no analytics, and sends no crash reports. It contacts the internet only for:
- Update checks: one request for the list of releases on GitHub, at launch and once a day, with nothing about you or your Mac. Turn them off in Settings ▸ General ▸ Updates. Updates install only when you choose, and only if they're signed with Runlet's key.
- Runlet's own PHP, only when you click to download it. It's checked against a SHA-256 checksum built into the app.
- Remote images in a preview, only when you allow them for that preview.
- AI requests, only when you click Send in an AI feature or Test Key in Settings ▸ AI: straight to Anthropic or OpenAI, with your own key.
Code You Trust
Some code runs with the same permissions as your snippets, so treat it as you treat your application's code:
- Project drivers in a project's
.runletfolder boot the application for every run, and can add commands. - AI clients' code runs only after you approve it on the sheet that shows all of it. Read it as you would a pull request.