# Reference: Settings Fields > Every settings field with its exact name, type, default, and effect — useful for > reading or writing the JSON directly. Source of truth: > `App/Sources/Features/Settings/Models/GlobalSettings.swift` and `RepositorySettings.swift`. **Keywords:** settings fields, global settings, repository settings, defaults, settings.json, prowl.json, config, json schema For the UI grouping of these into tabs, see [`components/settings.md`](../components/settings.md). ## On-disk locations | Scope | Path | |-------|------| | Global settings | `~/.prowl/settings.json` | | Global custom commands + agent profiles + workflows | `~/.prowl/global.user.json` | | Per-repository settings | `~/.prowl/repo/-/prowl.json` | | Per-repository custom commands + agent-profile memory | `~/.prowl/repo/-/prowl.user.json` | JSON is pretty-printed with sorted keys. `` is the first 8 hex digits of the SHA-256 of the repository path (trailing slash removed). Files in the per-name directory of earlier versions (`~/.prowl/repo//`) are copied on first load and never deleted; icons there are read in place. Legacy `~/.supacode` is migrated to `~/.prowl` on first launch. ### User settings migration When a new user settings path is absent, Prowl reads an earlier file and creates the new path from it; the old file is not deleted. If both exist, the new path wins. - **Global:** `global.onevcat.json` in `~/.prowl/`. - **Repository user settings:** from the per-name directory of earlier versions, `~/.prowl/repo//`, in this order: `prowl.user.json`, `prowl.onevcat.json`, `supacode.onevcat.json`. A file placed in the new `-/` directory under an old name is not read. For these two user settings files, migration preserves the original JSON bytes. New regular files are owner-only (`0600`). A legacy symlink produces a new symlink to the same resolved target, so dotfiles-backed settings stay connected. A damaged, unreadable, or dangling configuration stops loading and saving; Prowl does not replace it with defaults or recover from an older file silently. To recover, quit Prowl, back up the files, repair the JSON, permissions, or link target, then restart. Read and migration failures are recorded in the Settings log. ### Repository settings migration Repository settings (`prowl.json`) follow a looser policy. When `~/.prowl/repo/-/prowl.json` is absent or cannot be decoded, Prowl reads `prowl.json`, then `supacode.json`, from the per-name directory of earlier versions, then the repository's entry in `settings.json`. A legacy file is re-encoded into the new path (a symlink stays a link to the same target), so a damaged new `prowl.json` is **replaced** by the older settings when a legacy file exists. Back up the new file before you repair it by hand. Old regular files are migration-time snapshots, not synchronized backups. Downgrading to an older Prowl version does **not** carry later changes back to those files. Symlink-backed old and new paths share one target instead. Legacy reads have no scheduled removal date. ## Global settings (`GlobalSettings`) | Field | Type | Default | Effect | |-------|------|---------|--------| | `appearanceMode` | enum (`system`/`light`/`dark`) | `dark` | App appearance. | | `defaultEditorID` | String | `auto` | Default app to open worktrees (overridable per repo); `auto` prefers an app matching the detected project type. | | `confirmBeforeQuit` | Bool | `true` | Confirm before quitting Prowl. | | `updatesAutomaticallyCheckForUpdates` | Bool | `true` | Background update checks. | | `updatesAutomaticallyDownloadUpdates` | Bool | `false` | Auto-download updates. | | `inAppNotificationsEnabled` | Bool | `true` | In-app alerts / bell indicators. | | `notificationSound` | enum (`never` / system sound raw values like `hero` / `supacodeClassic`) | `supacodeClassic` | Sound played for notifications when system banners are off; `never` disables it. Migrates the legacy `notificationSoundEnabled` Bool (`true` → `supacodeClassic`, `false` → `never`); unknown raw values fall back to the default. | | `systemNotificationsEnabled` | Bool | `false` | macOS system banners. | | `muteNotificationsForActiveSurface` | Bool | `true` | Suppress the banner, sound, and dock bounce when the notification's pane is the one you're actively viewing (selected worktree, focused pane, key + visible window). Workflow status-edge notices use selected-worktree visibility because their status is worktree-level. | | `moveNotifiedWorktreeToTop` | Bool | `true` | Float a notified worktree to top. | | `commandFinishedNotificationEnabled` | Bool | `true` | Notify when a long command finishes. | | `commandFinishedNotificationThreshold` | Int (seconds) | `10` | Minimum duration before that notification fires. | | `analyticsEnabled` | Bool | `true` | Send usage analytics (PostHog; off in Debug). | | `crashReportsEnabled` | Bool | `true` | Send crash reports (Sentry). | | `githubIntegrationEnabled` | Bool | `true` | Enable GitHub/PR features (via `gh`). | | `deleteBranchOnAutomaticCleanup` | Bool | `false` | Delete the local branch when automatic cleanup (merged-PR delete action, archived auto-delete) removes a Prowl-created worktree. Migrates the legacy `deleteBranchOnDeleteWorktree` key. The manual delete dialog is independent: it remembers the last confirmed choice in UserDefaults (`deleteBranchOnManualWorktreeDelete`). | | `mergedWorktreeAction` | enum? | `nil` | What to do with a merged worktree (e.g. auto-archive); `nil` = ask. | | `promptForWorktreeCreation` | Bool | `true` | Show the creation dialog vs. auto-create. | | `fetchOriginBeforeWorktreeCreation` | Bool | `true` | `git fetch` before creating a worktree. | | `defaultWorktreeBaseDirectoryPath` | String? | `nil` | Default parent directory for new worktrees. | | `copyIgnoredOnWorktreeCreate` | Bool | `false` | Copy `.gitignore`'d files into new worktrees. | | `copyUntrackedOnWorktreeCreate` | Bool | `false` | Copy untracked files into new worktrees. | | `pullRequestMergeStrategy` | enum (`merge`/`squash`/`rebase`) | `merge` | Default PR merge strategy. | | `restoreTerminalLayout` | Bool | `true` | Restore tabs/splits on launch. Replaces `restoreTerminalLayoutOnLaunch`: Prowl ignores the old field, so the setting turns on once for every existing settings file. | | `terminalFontSize` | Float32? | `nil` | Remembered terminal font size; `nil` follows Ghostty's `font-size`. A size equal to Ghostty's `font-size` is stored as `nil`, also at launch. | | `ghosttyConfigPath` | String? | `nil` | Dedicated Ghostty config file for Prowl; replaces Ghostty's own config files. `nil` = share Ghostty's config. | | `archivedAutoDeletePeriod` | enum? (days) | `nil` | Auto-delete archived worktrees after N days; `nil` = never. | | `keybindingUserOverrides` | object | empty | User keyboard-shortcut remappings. | | `defaultViewMode` | enum (`normal`/`shelf`/`canvas`) | `normal` | View mode on launch. | | `canvasDefaultLayout` | enum (`uniform`/`tile`) | `tile` | Layout a fresh Canvas starts in: `uniform` packs same-size cards (Arrange), `tile` resizes cards to fill the screen. Canvas then keeps the layout you last chose. | | `dimUnfocusedSplits` | Bool | `true` | Dim panes that aren't focused. | | `autoShowActiveAgentsPanel` | Bool | `false` | Auto-open the Active Agents panel on a new agent. | | `showActiveAgentTabTitles` | Bool | `false` | Show pane titles (surface title, falling back to the tab title; vs. branch) in the agents panel. | | `showActiveAgentNames` | Bool | `true` | Show the agent name before the repository name in agents panel rows; when off, the name moves to the row's tooltip. Agent Island is not affected. | | `showActiveAgentStatusInShelf` | Bool | `true` | Show agent status markers on Shelf tab icons. | | `agentIslandSilentOpacity` | Double | `0.35` | Quiet floating island opacity (0.2–1.0), under Agents → Display. Notched monitors stay fully opaque. | | `agentIslandEnabled` | Bool | `false` | Show Agent Island, including its empty state unless `agentIslandOnlyShowWithAgents` is enabled. | | `agentIslandOnlyShowWithAgents` | Bool | `false` | Hide Agent Island when the Active Agents roster is empty. | | `agentIslandFloatingPositions` | object (`{"positionsByDisplayID":{}}`) | Empty positions | Saved horizontal positions per display UUID (0–1); absent entries use the center. Applies to displays without a notch. | | `agentIslandDisplayPreference` | object (`{"mode":"automatic"}` or `{"mode":"display","id":"","name":""}`) | `{"mode":"automatic"}` | Select Agent Island placement. A missing fixed display temporarily follows Automatic while preserving its UUID for reconnection. | | `windowTintMode` | enum (`none`/`repositoryColor`/`custom`) | `repositoryColor` | How the window chrome is tinted. | | `windowTintCustomColor` | color | default | The custom tint color (when `windowTintMode = custom`). | | `showRunButtonInToolbar` | Bool | `true` | Show the Run Script button in the toolbar. | | `showDefaultEditorInToolbar` | Bool | `true` | Show the open-in-editor button in the toolbar. | | `dockBounceMode` | enum (`off`/`once`/`continuous`) | `off` | Dock bounce on notification. | | `showNotificationDotOnDock` | Bool | `false` | Numeric unread badge on the Dock icon. | | `shelfSpineTintFallback` | enum (`neutral`/`systemTint`) | `neutral` | Shelf spine color when a repo has no color. | | `shelfSpineTintFollowsRepositoryColor` | Bool | `true` | Tint shelf spines by repo color. | | `externalDiffToolID` | String | `built-in` | Tool used by diff badges and Show Diff: `built-in`, `hunk`, `filemerge`, `kaleidoscope`, or `custom`. | | `externalDiffCustomCommand` | String | `""` | Command template for `externalDiffToolID = custom`; supports `{leftPath}`, `{rightPath}`, `{worktreePath}`, `{repoPath}`, and `{branch}`. | | `detectRepositoryIconsAutomatically` | Bool | `true` | Scan newly added repositories locally for a high-confidence project icon (app icon, launcher, favicon/logo) and use it as the repo icon. Applies to future additions only; never replaces a manual icon. | ## Per-repository settings (`RepositorySettings`) Stored at `~/.prowl/repo/-/prowl.json` (schema v2). For the tri-state `Bool?` fields, `nil` means "inherit the global setting." | Field | Type | Default | Effect | |-------|------|---------|--------| | `setupScript` | String | `""` | Script run automatically after a worktree is created. | | `archiveScript` | String | `""` | Script run automatically before a worktree is archived. | | `runScript` | String | `""` | The on-demand Run Script (`⌘R`). | | `openActionID` | String | `auto` | App to open this repo's worktrees (overrides `defaultEditorID`); `auto` prefers an app matching the detected project type. | | `worktreeBaseRef` | String? | `nil` | Default base branch/ref for new worktrees. | | `worktreeBaseDirectoryPath` | String? | `nil` | Parent directory for new worktrees (overrides global). | | `copyIgnoredOnWorktreeCreate` | Bool? | `nil` | Copy ignored files; `nil` = use global. | | `copyUntrackedOnWorktreeCreate` | Bool? | `nil` | Copy untracked files; `nil` = use global. | | `pullRequestMergeStrategy` | enum? | `nil` | PR merge strategy; `nil` = use global. | | `githubAccountOverride` | object? | `nil` | Optional `{ "host": "...", "login": "..." }`; Prowl temporarily switches `gh` to this account for GitHub operations in this repo. | | `customTitle` | String? | `nil` | Display name override for the repository. | | `observeLineDiffsAutomatically` | Bool? | `nil` (= on) | Keep worktree line-change badges updated; set `false` for large repos. | | `fetchPullRequestState` | Bool? | `nil` (= on) | Background-fetch PR state; set `false` to save GitHub rate limit. | **Custom Commands** live separately in `prowl.user.json`. Each command has an `isEnabled` Boolean that defaults to `true`; turning it off preserves its structure (title, icon, command, execution mode, close-on-success, shortcut, and order) but removes it from every command surface and hotkey dispatch. **Global Custom Commands** use the same command structure in `~/.prowl/global.user.json`. Repository `prowl.user.json` files additionally store `disabledGlobalCommandIDs`: an absent ID means enabled for that repository, while an included ID hides that Global command there. Local commands are ordered before Global commands; matching titles do not hide either command. **Agent Profiles** share these files: `global.user.json` also stores the `agentProfiles` array and the one-shot `didSeedAgentProfiles` flag, and each repository's `prowl.user.json` stores `defaultAgentProfileID` (the explicit per-repo Default Agent Profile) and `lastLaunchedAgentProfileID` (launch memory for the Recommended resolution). See [`components/agent-profiles.md`](../components/agent-profiles.md). **Workflows** also persist in `global.user.json`: `disabledWorkflowIDs` (`bundle/`, `user/`, or `repo:/` keys of workflow definitions switched off — the Enabled control in Workflow Settings), `workflowBindModeOverrides` (`{workflow_key, mode}` entries, `mode` `ask` | `auto`; absent = follow the file's `bind` — the detail's Run Setup picker and the start sheet's "Don't ask again"), and `workflowBindings` (remembered `launch`-role Profile bindings, one per requirements digest — the page's per-role pickers, or a start that resolved the role). Prefer the page over editing them by hand. See [`components/workflows.md`](../components/workflows.md). ## Notes for agents - Defaults here are the **factory** values; a human's file may differ. - Tri-state `Bool?` per-repo fields: `nil`/absent = inherit global; `true`/`false` = explicit override. - Editing the JSON while Prowl is running may be overwritten on save — prefer the Settings UI, or change settings while the app is closed. - The application language is **not** in `settings.json`. Settings → General → Language reads and writes the per-app `AppleLanguages` default (`defaults read com.onevcat.prowl AppleLanguages`), the same key as System Settings → Language & Region → Applications. No key means "follow the system". A change takes effect on the next launch.