From 045b204659b4b832c060d8d184adf20e5294a9d4 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Tue, 21 Jul 2026 17:03:52 +0000
Subject: [PATCH 66/71] docs(macos): document available NSUserDefaults settings
 and how to persist them

Consolidates the 7 settings main.mm already reads (theme, renderer, fontFamily,
fontSize, ssh, shell, scrollbar) into one reference: the env-var/NSUserDefaults/
built-in-default resolution order, the defaults key/type/env-var/default for each,
and copy-pasteable `defaults write` examples. This information previously only
existed scattered across main.mm's inline comments and individual feature commit
messages, with no single place to look it up.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LzTmVgP2ruMz987VJ78k77
---
 docs/macos-roadmap.md  |  3 +++
 docs/macos-settings.md | 60 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 docs/macos-settings.md

diff --git a/docs/macos-roadmap.md b/docs/macos-roadmap.md
index 24cdf38b..0f3936d9 100644
--- a/docs/macos-roadmap.md
+++ b/docs/macos-roadmap.md
@@ -11,6 +11,9 @@ includes colorschemes, fullscreen, tabs/splits, scrollbar, history, bell, opacit
 permissions, mouse, image protocols, terminal_id) — "normal minimal features users expect,
 plus whatever is cheap to add," not visual parity with the Qt GUI.
 
+For the settings already available today (theme, font, render backend, scrollbar, SSH, shell)
+and how to persist them, see [macos-settings.md](macos-settings.md).
+
 ## Known open issues (pre-existing, tracked)
 
 - **Uneven character spacing** — `advanceToCells` rounds per-glyph advances to whole cells;
diff --git a/docs/macos-settings.md b/docs/macos-settings.md
new file mode 100644
index 00000000..44d2f981
--- /dev/null
+++ b/docs/macos-settings.md
@@ -0,0 +1,60 @@
+# macOS frontend settings
+
+The native AppKit frontend (`src/contour_macos/`) has no preferences UI yet (tracked as
+roadmap item #9/#24 — a settings window and/or YAML config file, sharing this same
+persistence layer). Until then, every setting is read once at launch from two places, in
+priority order:
+
+1. **Environment variable** — highest priority, meant for one-off/quick testing
+   (`CONTOUR_THEME=light contour`). Not persisted.
+2. **`NSUserDefaults`** — persists across launches, editable with the `defaults` CLI or any
+   plist editor. Stored at `~/Library/Preferences/org.contourterminal.Contour.plist`, under
+   the app's bundle identifier `org.contourterminal.Contour`.
+3. **Built-in default** — used when neither of the above is set.
+
+Set a persisted value with:
+```
+defaults write org.contourterminal.Contour <key> <value>
+```
+Remove one (falling back to the built-in default) with:
+```
+defaults delete org.contourterminal.Contour <key>
+```
+Changes take effect on the **next launch** — there is no live-reload yet.
+
+## Available settings
+
+| Setting | `defaults` key | Type | Env var | Built-in default | Notes |
+|---|---|---|---|---|---|
+| Color theme | `theme` | string | `CONTOUR_THEME` | `dark` | Any value other than `light` is treated as `dark`. |
+| Render backend | `renderer` | string | `CONTOUR_RENDER` | `cpu` | `gl` or `opengl` selects the OpenGL 2.0 backend; anything else is the CPU (CoreGraphics) backend. |
+| Font family | `fontFamily` | string | — | `Menlo` | No env override (font testing is rare enough to not need one). |
+| Font size | `fontSize` | float | — | `14.0` | Values `<= 0.0` are treated as unset and fall back to the default. |
+| SSH destination | `ssh` | string | `CONTOUR_SSH` | *(unset = local shell)* | `user@host[:port]`. An empty/unset value spawns a local shell instead of connecting over SSH. |
+| Shell override | `shell` | string | — | *(unset = account's login shell)* | No env override; `$SHELL` is deliberately **not** consulted — set this key if you want something other than the account's login shell (`pw_shell`). |
+| Scrollbar | `scrollbar` | bool | `CONTOUR_SCROLLBAR` | `false` (off) | Classic always-visible `NSScroller`, right side, auto-hides while the alternate screen (vim/less/etc.) is active. Env var accepts `0`/`off`/`false` (case-insensitive) as falsy, anything else as truthy. |
+
+## Examples
+
+```
+# Persist a light theme and a bigger font
+defaults write org.contourterminal.Contour theme light
+defaults write org.contourterminal.Contour fontFamily Monaco
+defaults write org.contourterminal.Contour fontSize -float 16
+
+# Turn the scrollbar on persistently
+defaults write org.contourterminal.Contour scrollbar -bool true
+
+# One-off GL-backend test without touching persisted settings
+CONTOUR_RENDER=gl contour
+
+# Persist a default SSH destination (every new window connects there)
+defaults write org.contourterminal.Contour ssh someuser@example.com
+```
+
+## Where this is implemented
+
+All resolution happens in `src/contour_macos/main.mm`'s `openTerminalWindow` (the settings are
+read once per window, at creation — an already-open window does not react to a
+`defaults write` until it is closed and a new one opened). Search that file for
+`NSUserDefaults` to see the exact resolution code for each setting above.
