Files
tty7/docs/reference/privacy.mdx
T
l0ng-ai 3064ce8a68 fix(history): stop per-pane history from silently disabling history search
`<config>/history` was two different things at once. The window keeps the
input bar's command store there as a *file* (`terminal::history`), and the
daemon put each pane's `HISTFILE` in a *directory* of the same name. A path
is one or the other, and the daemon created its directory the moment
`per_pane_history` was switched on, so the daemon won.

After that the window's `append` opened a directory, got an error, and — the
call site being `if let Ok(mut f) = open(..)` — dropped the command line
without a word. Up and Ctrl-R went on offering whatever had been recorded
before the setting was turned on and never grew again. Nothing in the UI or
the log said why, and the two halves are in different crates, so neither side
had any reason to notice the other's name.

Per-pane files move to `<config>/pane-history/`, which leaves the old name to
the file that should have had it. An install that already tripped over this
is carried across on the next start: the directory sitting at the old name is
exactly what belongs at the new one, so it is renamed rather than abandoned —
but only when it *is* a directory, since a plain file there is the window's
store and moving that would take the very thing this repairs, and only when
the new name is free, so a second call cannot bury a directory in use.

Verified end to end against a daemon: with the setting on it now creates
`pane-history/` 0700 with the pane files in it, and an append to
`<config>/history` succeeds where it previously failed. Seeding an
old-layout install with `history/pane-9` and starting the daemon leaves the
line intact at the new path.

Guards: one reads the window's source for the names it passes to
`config_path` and fails if the daemon's directory is among them, so moving
either side onto the other trips it; one covers the three ways the move can
lose data (directory moves, file stays, occupied target is not overwritten).
Both were checked against injected regressions. The privacy page and the
integration test that read the path follow it.
2026-08-23 02:46:54 +08:00

64 lines
3.8 KiB
Plaintext

---
title: "Privacy and permissions"
description: "What macOS asks you, why, and what tty7 itself holds."
---
## Why macOS asks tty7 for permission
Panes are forked from tty7's own bundled executable, so when a program you run
asks macOS for a protected resource, macOS attributes the request to **tty7.app**
— not to the program.
If tty7 declared no usage strings, that request would be **denied outright with
no prompt at all**, and the program would look broken for no visible reason.
So tty7 declares the matching usage strings, and you get the normal one-time
prompt:
<CardGroup cols={2}>
<Card title="Devices" icon="camera">
Camera · microphone · Bluetooth · location · motion
</Card>
<Card title="Personal data" icon="address-book">
Contacts · calendars · reminders · photo library
</Card>
<Card title="System" icon="gear">
Local network · Apple Events · speech recognition · system administration
</Card>
</CardGroup>
<Warning>
**Declaring a usage string is not the same as holding the permission.**
tty7.app itself is granted none of these. Every prompt you see belongs to
whatever you ran in the pane, and you can revoke it under **System Settings →
Privacy & Security**.
</Warning>
### Full Disk Access
Apple defines no usage-string key for it. Reaching `~/Library/Mail`,
`~/Library/Messages`, `~/Library/Safari`, or `~/Library/Containers` needs a
manual grant in **System Settings → Privacy & Security → Full Disk Access**.
## What leaves your machine
| | |
|---|---|
| **Update checks** | A request to the GitHub releases API every six hours, plus the download when you accept one. Turn it off with `check_for_updates: false`. |
| **Remote server installs** | Downloading a `tty7-server` binary for a machine you connected to — or, for WSL, copying the one already bundled with your install. |
| **Everything else** | Nothing. There is no telemetry, no analytics, and no account. |
Both of the above honour `http_proxy`. [Updates →](/reference/updates#proxies)
## What is stored, and where
| | |
|---|---|
| Settings, themes, window state | `~/.config/tty7/` (`%APPDATA%\tty7\` on Windows) |
| SSH passwords and key passphrases | The **OS keychain** — never `config.json`, never plain text on disk |
| Pane scrollback tails | `<config>/scrollback/*.bin`, mode `0600` on Unix and behind the config directory's ACL on Windows. 256 KiB per pane, kept only until something can no longer ask for it: closing a pane deletes its file at once, a restore consumes it, and a periodic pass collects the rest. |
| Shell history | Your shell's own file, exactly as before. With **per-pane history** on, tty7 points each pane's `HISTFILE` at `<config>/pane-history/pane-<n>` instead — the directory is created `0700`, and the files in it are written by your shell, under your umask, holding the command lines you ran in that pane. A pane's additions merge back into your usual history file when it closes. |
| Crash reports | `<config>/crash.log`, appended whenever tty7 panics: the time, the version, the panic message and a backtrace. Capped at 256 KiB. Nothing uploads it — it is there for you to read, and to attach to an issue if you choose. |
| Update log | `<config>/update.log`, appended by the updater while it installs a release: what it verified, what it replaced, and why it stopped if it did. Written whenever an update runs, not only under `TTY7_LOG` — the swap happens after the window is gone, so this is the only account of it. Nothing uploads it. |
| Diagnostic log | `<config>/tty7.log`, written **only** while `TTY7_LOG` (or `RUST_LOG`) is set; unset, there is no log at all. At `info` it records the daemon and connection lifecycle. At `debug` it also carries the directories and workspace names each request names, and output from the libraries tty7 is built on — worth reading before you attach it to an issue. Capped at 4 MiB. |