# 15 — Settings

## AI grep hints

- Keys: `settings.*` (full namespace — over 400 keys; section roots listed below), including General keys `settings.autoStartWithWindows`, `settings.minimizeToTray`, `settings.useDirectxScreenCapture`, `settings.statusBar`, `settings.statusBarVisible`, `settings.statusBarMonitor`, `settings.statusBarMonitorInterval`, `settings.debug`, `settings.advancedDebugging`, `settings.openLogFolder`, Don't Sleep keys `settings.sectionDontSleep`, `settings.dontSleepForegroundOnly`, SSH X server keys `settings.xServer*`, Appearance keys for theme/font/layout, and AI provider keys `settings.apiMode`, `settings.apiModeChatCompletions`, `settings.apiModeResponses`, `settings.extraHeaders`, `settings.extraHeadersPlaceholder`, `settings.useCodexCli`, `settings.useClaudeCli`, and `settings.assistantSkills*`
- Topics: General, Appearance, Workspace (`settings.workspace`), Dashboard, File Explorer (`settings.fileExplorer`), Don't Sleep (`settings.dontSleep`), Install Helper (`settings.installer`), Credentials & MCP, AI Assistant, assistant tool defaults, collapsible assistant tools, collapsible Assistant Skills, bundled skills, SKILL.md, SSH, managed VcXsrv X server launcher, Terminal, network troubleshooting, DNS, DHCP, firewall, TLS certificates, RDP, VNC, URL, About; settings draft/save/reset; `.kkbackup` import/export; reset all; Windows startup; launch minimized; DirectX screenshot capture; Status Bar visibility; Status Bar CPU/RAM/Network monitor; custom title bar; RDP session stability (WebView2); Advanced Debugging; AI Assistant debug logs; MCP debug logs; URL Connection debug logs; SFTP debug logs; built-in MCP config; random dynamic Dashboard backgrounds; terminal default transparency; random dynamic terminal backgrounds; hidden top Tab Strip; Child Connection Tabs in the Connection Tree; foreground-only keep-awake behavior
- Synonyms: "preferences", "options", "config", "theme", "dark mode", "color", "language", "API key", "Codex CLI", "Claude Code CLI", "Claude CLI", "CLI backend", "CLI auth", "import settings", "factory reset", "show me where", "start with Windows", "run at login", "launch minimized", "custom title bar", "titlebar", "window chrome", "DirectX", "DXGI", "screen capture", "screenshot acceleration", "status bar", "show status bar", "hide status bar", "CPU monitor", "RAM monitor", "network monitor", "host usage", "performance overhead", "debug", "diagnostics", "open logs", "log folder", "AI debug log", "MCP debug log", "Install Helper debug log", "URL Connection debug log", "URL debug log", "SFTP debug log", "heartbeat debug log", "aiassistant.debug.log", "mcp.debug.log", "installer.helper.debug.log", "url.connection.debug.log", "sftp.debug.log", "kkterm-heartbeat.debug.log", "ui.debug.log", "UI debug log", "terminal focus", "MCP config", "mcpServers", "mcp_servers", "TOML", "kkterm-cli", "Codex MCP", "Claude MCP", "expand tools", "collapse skills", "random wallpaper", "dynamic wallpaper", "dashboard background", "terminal wallpaper", "terminal transparency", "terminal background", "top tabs", "tab buttons", "hide tabs", "connection tree tabs", "child tabs", "saved tabs", "X11", "X forwarding", "X server", "VcXsrv", "network-connectivity-troubleshooter", "dashboard-widget-designer", "dashboard-data-visualization", "desktop-accessibility-ui", "dns-dhcp-troubleshooter", "firewall-port-troubleshooter", "tls-certificate-troubleshooter"

## Software updates

Automatic and manual checks normally read `https://kkterm.ryantsai.com/releases/latest.json`. If that app-owned Cloudflare endpoint is unavailable or returns invalid metadata, KKTerm falls back to GitHub Releases. On Windows, installer and checksum downloads also retry the same release asset on the other trusted host if the selected host cannot complete the fetch. A successful check records its time; automatic startup checks are limited to once per 24 hours, while `settings.checkForUpdates` always performs a fresh manual check.

Update checks are not telemetry. They do not upload Connection, Session, Tab, terminal, credential, or usage data. Windows downloads remain protected by the published SHA-256 checksum, and macOS/Linux updates retain Tauri signature verification regardless of whether Cloudflare or GitHub serves the files.

> Settings page styling is consistent across sections. Related controls live inside the shared `settings-subsection settings-fieldset` group, and subsection titles use the shared 12px bottom margin before the normal layout gap. Keep that spacing on the shared title/legend style rather than the first control. Editable controls look editable; disabled / readonly controls stay muted. Delete buttons inside Settings are icon-only red trash cans (no visible "Delete" text). Destructive Settings-wide actions live in **General → Settings data**, behind app-owned confirmation dialogs — not inside feature-specific sections.
> Related Settings rows should stay grouped together inside the same subsection whenever they describe the same topic. Avoid standalone one-row cards for related options; use one fieldset with consecutive rows so the page reads as a compact option group. Hide platform-specific subsections when the current platform has no available rows.

Settings is owned by `src/modules/settings/SettingsPage.tsx` and opens as an app-owned popup over the current Module. Its blocking backdrop covers and disables the Activity Rail as well as the active Module while Settings is open. Persisted bootstrap (`useBootstrapSettings`) lives in `src/lib/settings.ts`; add new persisted settings there, not via cloned effects in `src/App.tsx`.

The universal AI Assistant panel remains visible on Settings. `src/modules/settings/settingsAssistantContext.ts` publishes the active section, visible control keys, and tutorial targets to the assistant. The Tutorial tool can navigate to the owning Settings section before highlighting known targets after the user accepts a navigation offer.

Platform-specific controls are shown only where the runtime supports them. Windows-only controls such as `settings.autoStartWithWindows`, `settings.minimizeToTray`, `settings.useDirectxScreenCapture`, `settings.rdpWebviewStability`, `settings.sectionInstaller`, and `settings.sectionRdp` are hidden in the macOS and Linux builds.

General includes one `settings.activityRail` group for the built-in rail destinations and control. It shows, hides, and reorders by dragging the Workspace (`settings.sectionWorkspace`), Dashboard (`settings.sectionDashboard`), Install Helper (`settings.sectionInstaller`, Windows only), and IT Ops (`settings.sectionItOps`) Modules. These rows use the same colored identity tiles and glyphs as their Module headers. At least one Module must remain enabled. Don't Sleep (`settings.sectionDontSleep`) can be hidden separately and stays with Settings at the bottom of the rail. The reordered Module sequence is saved with the General settings. Workspace, Dashboard, Install Helper, and Don't Sleep default on; IT Ops defaults off. The connected Connection shortcut toggle remains in Workspace because it controls live/pinned Connection entries rather than a built-in Module. Settings navigation also reuses the matching Module identity tile when a dedicated section exists, currently Workspace, Dashboard, and Install Helper.

Settings tutorial targets:

- General: `settings.language`, `settings.workspaceAccess`, `settings.useDirectxScreenCapture`, `settings.statusBar`, `settings.settingsData`, `settings.debug`.
- Appearance: `settings.appUiFontFamily`, `settings.appearance.colorScheme`, `settings.resetLayout`.
- Workspace: `settings.connectedConnectionsRail`, `settings.hideTopTabButtons`, `settings.doubleClickOpensConnection`, `settings.submitAiAttachmentsDirectly`, `settings.separateSplitTerminalBackgrounds`.
- File Explorer: `settings.fileExplorerOpenMode`, `settings.fileExplorerTerminal`.
- Dashboard: `settings.dashboardDefaultLanding`, `settings.dashboardUseRandomDynamicBackground`, `settings.dashboardMaxActiveScriptWidgets`.
- Credentials: `settings.credentialStorage`, `settings.encryptedSecretStoreSetupTitle`,
  `settings.encryptedSecretStoreSetupAction`, `settings.encryptedSecretStoreSetupRequiredTitle`, `settings.credentialsStored`,
  `settings.widgetCredentialsStored`.
- AI Assistant: `settings.aiProvider`, `settings.aiToolsTitle`, `settings.aiCustomInstructions`, `settings.assistantSkillsTitle`, `settings.mcpServersTitle`, `settings.allowInsecureMcpHttp`.
- SSH: `settings.defaultUser`, `settings.defaultPort`, `settings.defaultKey`, `settings.proxyJump`, `settings.sshBufferLines`. (The SSH SOCKS proxy default moved to Settings → Proxy; per-Connection SSH SOCKS overrides remain in the add/edit Connection dialog.)
- Terminal: `settings.terminalFontFamily`, `settings.terminalFontSize`, `settings.defaultShell`, `settings.customShells`, `settings.scrollbackLines`.
- URL: `settings.ignoreCertificateErrors`, `settings.urlSavedPasswords`, `settings.urlDataShards`.
- RDP: `settings.rdpColorDepth`, `settings.rdpPerformanceProfile`.
- VNC: `settings.vncViewOnly`, `settings.vncColorLevel`.
- Proxy: `settings.proxy` (navigation `settingsSectionId=proxy-settings`).
- About: `settings.aboutVersion`.

## Page chrome

- Page title `settings.title`.
- Left sidebar label `settings.sectionsNav`. Sections:
  - `settings.sectionGeneral`
  - `settings.sectionAppearance`
  - `settings.sectionDashboard`
  - `settings.sectionWorkspace`
  - `settings.fileExplorer`
  - `settings.sectionInstaller`
  - `settings.sectionCredentials`
  - `settings.sectionAiAssistant`
  - `settings.sectionSsh`
  - `settings.sectionTerminal`
  - `settings.sectionRdp`
  - `settings.sectionVnc`
  - `settings.sectionUrl`
  - `settings.sectionDontSleep`
  - `settings.proxy`
  - `settings.sectionAbout`
- Save action: `settings.save`. When any visited section has unsaved edits, the popup header shows `settings.changesNotSaved` followed by the Save button immediately to the left of the close button. Switching Settings sections preserves each visited section's draft until it is saved or Settings is closed. When all sections are clean, both the text and Save button are hidden. Clicking outside the Settings popup or using the top-right close button closes it only while there are no unsaved edits; otherwise the warning dialog uses `settings.unsavedQuitTitle`, `settings.unsavedQuitBody`, `settings.saveAndQuit`, `settings.quitWithoutSaving`, and `common.cancel`.
- Per-section status, e.g. `settings.appearanceSaved`, `settings.generalDefaultsSaved`.

## General

- Defaults group `settings.generalDefaults`.
- App Update subsection `settings.softwareUpdates`: shows the installed version with `settings.version`, the last manual update check with `settings.lastCheckedAt` / `settings.lastCheckedNever`, and the manual `settings.checkForUpdates` action. Startup update checks are controlled by `settings.autoUpdateChecks` (hint `settings.autoUpdateChecksHint`).
- Language picker: label `settings.language`. Native names come from the `languages` namespace. Changing the selection marks General dirty and applies only after `settings.save`. See [16-localization.md](16-localization.md).
- The global network proxy moved to its own top-level **Proxy** section (`settings.proxy`); see the [Proxy](#proxy) section below.
- Start with Windows minimized: toggle `settings.autoStartWithWindows` (hint `settings.autoStartWithWindowsHint`). When on, KKTerm registers itself for the current Windows user, launches after sign-in, and starts minimized; if `settings.minimizeToTray` is also on, the launch window hides to the system tray.
- Minimize to tray (Windows only): toggle `settings.minimizeToTray` (hint `settings.minimizeToTrayHint`). When on, the title-bar close button hides the window; when off, it exits. Tray "Exit" (`app.trayExit`) always quits. macOS and Linux do not show this control, and app-window close is not diverted there.
- Performance subsection `settings.performance`: toggle `settings.useDirectxScreenCapture` (hint `settings.useDirectxScreenCaptureHint`). When on, screenshot capture tries DXGI Desktop Duplication first and falls back to GDI when DirectX capture is unavailable or unsupported for the requested region.
- Status Bar subsection `settings.statusBar`: toggle `settings.statusBarVisible` (hint `settings.statusBarVisibleHint`) shows or hides the bottom Status Bar. Toggle `settings.statusBarMonitor` (hint `settings.statusBarMonitorHint`) controls whether the visible Status Bar shows and polls CPU/RAM/Network host metrics. When the Status Bar is hidden or the monitor toggle is off, KKTerm stops host usage polling completely. `settings.statusBarMonitorInterval` chooses the polling interval: `settings.statusBarMonitorInterval5`, `settings.statusBarMonitorInterval15`, `settings.statusBarMonitorInterval30`, `settings.statusBarMonitorInterval60`, or `settings.statusBarMonitorInterval300`.
- Settings data subsection (destructive actions live here):
  - Export: `settings.exportSettings` opens the selective export dialog with a switch per category (`settings.segment_connections`, `settings.segment_workspaces`, `settings.segment_dashboards`, `settings.segment_settings`, `settings.segment_mcpServers`) and an off-by-default `settings.includeCredentials` switch that, when enabled, requires a passphrase (`settings.exportPassphrase`) and warns via `settings.includeCredentialsWarning`. Produces a `.kkbackup` file; success `settings.selectiveExportComplete`.
  - Import: `settings.importSettings` opens the backup import dialog. Selecting a `.kkbackup` inspects the bundle and shows a per-category action selector — `settings.importActionSkip` / `settings.importActionAdd` / `settings.importActionReplace` — plus a passphrase field for encrypted bundles. Selecting a full `.zip` backup shows `settings.fullBackupImport` and restores the complete settings database through `settings.importSettingsComplete`, then reloads the app. See [17-data-backup-secrets.md](17-data-backup-secrets.md).
  - Reset all: `settings.resetAllSettings`, confirmation `settings.resetAllSettingsConfirm`, success `settings.resetAllSettingsComplete`.
- Debug subsection `settings.debug`: toggle `settings.advancedDebugging` (hint `settings.advancedDebuggingHint`) enables full AI Assistant, MCP, Install Helper, UI, URL Connection, RDP, SSH, SFTP, Telnet, and heartbeat debug log writing even in release builds. `settings.openLogFolder` opens the local log directory. KKTerm resolves that directory from the running `kkterm.exe` folder first and falls back to `%LOCALAPPDATA%\KKTerm\Logs` if the executable folder cannot be resolved. Enabling advanced debugging writes an `advanced_debugging.enabled` marker to the JSONL logs `aiassistant.debug.log`, `mcp.debug.log`, `installer.helper.debug.log`, `ui.debug.log`, `url.connection.debug.log`, `rdp.debug.log`, `ssh.debug.log`, `sftp.debug.log`, and `telnet.debug.log` beside `kkterm.log`, so the release logging path is visible before the next subsystem event. It also starts `kkterm-heartbeat.debug.log`; turning the setting off stops release heartbeat writes. The `ui.debug.log` records frontend UI diagnostics such as terminal focus-restore attempts (document focus state and the active element) used to troubleshoot input focus after switching apps. The `url.connection.debug.log` records URL Connection Session lifecycle, frontend DOM bounds, clipping, requested overlay bounds, native coordinate conversion, and WebView2 overlay window/client rectangles. The `rdp.debug.log` records RDP startup, ActiveX control creation, display-size sync, and main-thread command timing with non-secret Connection details, and defensively redacts password-like, secret-like, token-like, and credential-like fields. The `ssh.debug.log` records native SSH lifecycle, SOCKS proxy routing metadata with credentials stripped, keepalive configuration, channel open/close events, and terminal input/output byte counts without terminal contents. The `sftp.debug.log` records SFTP browser startup stages, per-session operation waits, transfer start/completion/error summaries, upload write/shutdown timeouts, and partial-upload cleanup without file contents or credential values. The `telnet.debug.log` records Telnet lifecycle, option names and codes, negotiation decisions, terminal-type and window-size events, errors, and byte counts without credential values or terminal contents. These local logs may include prompts, tool arguments, MCP arguments/results, Install Helper command output, URL hostnames, remote hostnames, usernames, proxy endpoints, local paths, remote paths, frontend/native liveness timing, screenshots, and generated Dashboard AI Created Widget source.
- RDP session stability (WebView2): toggle `settings.rdpWebviewStability` (hint `settings.rdpWebviewStabilityHint`) lives in the Debug subsection. When enabled, the next launch applies matching WebView2 stability browser arguments to the main app WebView and URL overlay WebViews while KKTerm runs inside an RDP host.

> Automatic database backups do **not** run from app-window close. Startup backups remain full ZIP snapshots; Settings Export creates `.kkbackup`, and Settings Import accepts `.kkbackup` or full backup `.zip`.

## Appearance

- Group `settings.appearanceInterface`.
- Colour scheme: `settings.colorScheme`. Schemes render as a grid of tappable preview cards (four columns) under the `settings.theme` grouping (hint `settings.themeHint`); each card shows a live mock of the app in that scheme plus its name, and the selected card is marked with a radio dot and check badge. Options: `settings.schemeDefault`, `settings.schemeDark`, `settings.schemeLight`, `settings.schemeMatchOs`, `settings.schemeMac`, `settings.schemeOrange`, `settings.schemePurple`, `settings.schemePink`, `settings.schemeGreenKuaiKuai`, `settings.schemeBlueSee`, `settings.schemeBlueGreenWhite`, `settings.schemeConfetti`, `settings.schemeBubbleTea`, `settings.schemeSemiconductor`, `settings.schemeCanarinho`, `settings.schemeLaAlbiceleste`, `settings.schemeLesBleus`, `settings.schemeOranje`, `settings.schemeDieMannschaft`, `settings.schemeLaRoja`, `settings.schemeOsNavegadores`, `settings.schemeVatreni`, `settings.schemeElTri`, `settings.schemeThreeLions`, `settings.schemeSamuraiBlue`, and `settings.schemeStarsAndStripes`. The `settings.schemeMatchOs` card shows a split light/dark preview with an `settings.schemeMatchOsBadge` badge. `settings.schemeMatchOs` resolves the operating system light/dark mode and Windows accent color when the app starts or when the user switches to that scheme; it does not continuously listen for OS changes.
- App UI font: `settings.appUiFontFamily` / `settings.activeUiFont`. Reset `settings.resetFont`. Validation `settings.appFontFamilyRequired`. Generic `settings.fontFamily` / `settings.fontSize` (range `settings.fontSizeRange`, blank check `settings.fontFamilyRequired`). The font dropdown is grouped as Custom fonts, Recommended, then System fonts: user-dropped custom fonts (`settings.customFonts`) stay first, the platform-specific `settings.recommendedFonts` group follows, and OS-detected fonts (`settings.systemFonts`) come last. Recommendations render from the static shared font catalog without scanning the OS; macOS favors SF Pro, Linux includes current GNOME/Ubuntu families, and Windows retains its native UI families. A refresh icon (`settings.refreshSystemFonts`) asynchronously re-scans both the app fonts folder and installed system fonts, filters unavailable recommendations, updates the Appearance and Terminal pickers through one shared snapshot, and caches the System fonts list so it survives an app relaunch. Cached fonts may populate the System group at startup, but recommendation filtering begins only after an explicit refresh in the current app run. TTF/OTF files sharing an internal family appear as one Custom fonts entry and supply every available weight/style face without requiring a complete family. Refresh status `settings.systemFontsRefreshed`, unavailable runtime `settings.systemFontsUnavailable`. The shared hint `settings.customFontsHint` appears under both the Appearance and Terminal font pickers, and the open-folder action stays an icon-only button keyed by `settings.openCustomFontsFolder`. When a scan returns localized aliases, KKTerm prefers English metadata names so the refreshed System fonts list does not duplicate Recommended entries. The scan also drops the operating system's hidden, dot-prefixed internal families (for example macOS `.SF NS`), which are not user-selectable, so they no longer appear in the System fonts group.
- KKTerm always uses app-painted custom title-bar chrome that follows the current KKTerm theme.
- Layout group `settings.layout`. Reset layout: `settings.resetLayout` (description `settings.resetLayoutDescription`) — resets Connections / AI panel widths.
- Save status: `settings.appearanceSaved`. Reset status `settings.appearanceReset`.

## Workspace

- Section header `settings.sectionWorkspace`.
- Activity Rail group `settings.activityRail`:
  - Toggle `settings.connectedConnectionsRail` (hint `settings.connectedConnectionsRailHint`). When on, connected Connection icons appear on the Activity Rail; when off, connected Connection shortcuts are hidden from the Activity Rail.
- Tabs group `settings.workspaceTabs`.
- Toggle `settings.hideTopTabButtons` (hint `settings.hideTopTabButtonsDesc`). When on, the top `workspace.tabStrip` buttons are hidden and new Tabs opened from saved Connections become **Child Connection Tabs**. Child Connection Tabs are shown as italic rows under their parent Connection in the active Workspace's Connection Tree, persist across launches, open lazily when selected, can be renamed, and expose `connections.childConnectionProperties` for child icon/color edits.
- Toggle `settings.doubleClickOpensConnection` (hint `settings.doubleClickOpensConnectionDesc`). The default is off: a single click opens a Connection from the Connection Tree. When on, a single click only selects the Connection row and a double-click opens it; users can rename Connections with `connections.rename` from the context menu.
- AI Assistant group `settings.sectionAiAssistant`.
- Toggle `settings.submitAiAttachmentsDirectly` (hint `settings.submitAiAttachmentsDirectlyDesc`). The default is on: Workspace Send to AI Assistant actions submit the captured screenshot or terminal buffer with `ai.directAttachmentPrompt`. When off, they only attach the context to the composer.
- Terminal backgrounds group `settings.terminalBackgrounds`.
- Toggle `settings.separateSplitTerminalBackgrounds` (hint `settings.separateSplitTerminalBackgroundsDesc`). The default is off: a Connection Tab paints one background behind the terminal workspace content area. When on, split terminal Panes can keep per-Pane terminal backgrounds; a single terminal Tab behaves the same as the default shared mode.
- Save status: `settings.workspaceSaved`.

## File Explorer

Section header `settings.fileExplorer`. Selector `settings.fileExplorerOpenMode` chooses how File Explorer (`localFiles`) opens local files. `settings.fileExplorerOpenModeExternal` keeps the default OS-app behavior; `settings.fileExplorerOpenModeInlineEditor` opens files in the inline Document/light editor surface when selected. Hint `settings.fileExplorerOpenModeHint`. Selector `settings.fileExplorerTerminal` chooses the shell used by the local-pane terminal icon (`sftp.openTerminalHereAria`): Windows offers normal and administrator variants of Command Prompt, PowerShell, and PowerShell 7 and defaults to normal PowerShell; macOS defaults to zsh; Linux defaults to bash. Named custom shells from Terminal settings are also available as normal launches. Hint `settings.fileExplorerTerminalHint`. Save status `settings.fileExplorerSaved`.

## Dashboard

- Section header `settings.sectionDashboard`. Title and description `settings.dashboardTitle` / `settings.dashboardDescription`.
- General group `settings.dashboardGeneral`:
  - Default landing view: `settings.dashboardDefaultLanding`. `settings.dashboardLandingLast` reopens the last active Dashboard View; other options are durable Dashboard View titles.
  - Random dynamic background: `settings.dashboardUseRandomDynamicBackground` (hint `settings.dashboardUseRandomDynamicBackgroundDesc`). When on, newly-created Dashboard Views automatically get one random dynamic background; existing Views are unchanged.
  - Widget network tools remain enabled for script widgets that declare `permissions.networkTools`. The underlying setting keys `settings.dashboardAllowWidgetNetworkTools` / `settings.dashboardAllowWidgetNetworkToolsDesc` are hidden from Settings for now.
- Performance group `settings.dashboardPerformance`:
  - Active script widgets cap: `settings.dashboardMaxActiveScriptWidgets` (hint `settings.dashboardMaxActiveScriptWidgetsHint`).

## Don't Sleep

- Section header `settings.sectionDontSleep`. Owned by `src/modules/settings/DontSleepSettings.tsx`.
- Activity Rail visibility is controlled by the unified General `settings.activityRail` group.
- Toggle `settings.dontSleepForegroundOnly` (hint `settings.dontSleepForegroundOnlyHint`). The default is on: when `app.dontSleep` is enabled, KKTerm asserts the OS keep-awake state only while the main window is focused and not minimized. When off, Don't Sleep uses the previous global behavior and keeps the OS awake while KKTerm is running even if the app is in the background or minimized.
- Save status: `settings.dontSleepSettingsSaved`.

## Install Helper

- Section header `settings.sectionInstaller`. Owned by `src/modules/settings/InstallerSettings.tsx`.
- Activity Rail visibility is controlled by the unified General `settings.activityRail` group.
- Update checks group `settings.installerUpdateChecks`:
  - Interval dropdown `settings.installerCheckInterval` (hint `settings.installerCheckIntervalDesc`) with options `settings.installerCheckInterval3600` (hour), `settings.installerCheckInterval86400` (day, default), `settings.installerCheckInterval604800` (week), `settings.installerCheckInterval2592000` (month). Controls how often the Install Helper auto-checks for the latest tool versions when you switch to the Module; the in-Module Refresh button always checks immediately.
- Save status: `settings.installerSaved`.

## Credentials & MCP

This is the central manager for secrets stored in the selected credential backend.

- Section header `settings.sectionCredentials`. Stored credentials list `settings.credentialsTitle` / `settings.credentialsStored` (hint `settings.credentialsHint`, empty `settings.credentialsEmpty`).
- Secret storage selector: `settings.credentialStorage` / `settings.credentialStorageBackend`. Windows and macOS default to `settings.credentialStorageOs` and can optionally switch to `settings.credentialStorageFile`; Linux exposes only `settings.credentialStorageFile`. The Credentials page shows a backend-specific security reminder: OS keystore storage uses the operating system credential manager and signed-in account, while encrypted database storage keeps encrypted rows in SQLite and depends on the master password plus database-file protection. Selecting `settings.credentialStorageFile` opens the setup dialog `settings.encryptedSecretStoreSetupTitle`, which repeats the security tradeoff before password entry. If no encrypted SQLite secret store exists, the dialog creates a master password and reminds the user to keep it safe because KKTerm cannot recover it. If one already exists, the dialog verifies the entered master password and unlocks the store. Linux users see a reminder that encrypted database storage is the available backend in this build and should protect the KKTerm database, backups, and `KKTERM_SECRET_STORE_PASSWORD` carefully. Encrypted database storage stays locked until the first feature that needs to read a saved secret, such as opening a Connection with a saved password, or until the user activates the Status Bar `app.credentialStoreUnlockAction`. The unlock dialog includes `settings.encryptedSecretStoreEnvironmentHint` to explain that setting `KKTERM_SECRET_STORE_PASSWORD` before launch lets KKTerm try to unlock the encrypted SQLite store automatically; if verification succeeds, the user does not need to type the master password for that app launch. Manually locking from the Status Bar clears the in-process unlock state, and manually unlocking from the Status Bar always shows the password dialog again. If decryption fails, the dialog can create a new master password, which invalidates and clears encrypted credentials saved with the previous password. The switch changes which backend KKTerm reads and writes from. It does not migrate existing secrets between stores.
- Per-credential fields: username `settings.credentialUsername`. Kinds (badges): `settings.credentialKindConnectionPassword`, `…UrlPassword`, `…AiApiKey`, `…EmailApiKey`, `…EmailSmtpPassword`, `…WidgetSecret`.
- Save status: `settings.credentialSavedPassword`, `…SavedApiKey`, `…SavedSecret`. Updated: `settings.credentialUpdated`. Missing secret error: `settings.credentialMissingSecret`. Stored marker: `settings.credentialStored`.
- Delete: red trash button `settings.deleteCredential`, confirmation body `settings.deleteCredentialConfirmBody`, status `settings.credentialDeleted`.
- Widget secrets subgroup: `settings.widgetCredentialsStored` (hint `…Hint`, empty `…Empty`).
- **MCP Servers** subgroup: title `settings.mcpServersTitle` (hint `…Hint`, empty `…Empty`). Actions:
  - Add: `settings.mcpAddServer` / `settings.mcpCreateServer`. Paste-JSON shortcut `settings.mcpPasteHint`, placeholder `…PastePlaceholder`, continue `…PasteContinue`, confirm hint `…ConfirmHint`.
  - Fields: `settings.mcpServerName`, `…ServerUrl`, `…HeadersLabel`. Detected secret hint `…DetectedSecretHint`. Per-secret header name / value template `…SecretHeaderName`, `…SecretValueTemplate`, `…SecretValue`.
  - Add-flow validation: `settings.mcpAddInvalidJson`, `…AddInvalidShape`, `…AddNoServers`, `…AddMissingUrl`, `…AddStdioUnsupported` (with stdio guidance `…StdioGuidance`).
  - Errors: `settings.mcpErrorNotFound`, `…ErrorDuplicateName`, `…ErrorKeychain`.
  - Status badges: `settings.mcpStatusOk`, `…Unreachable`, `…AuthError`, `…ProtocolError`, `…Unknown`. Tools count `settings.mcpToolsCount` / `…_one`. Auth badge `…AuthBadge`.
  - Refresh tools: `settings.mcpRefreshTools`. Delete: `settings.mcpDeleteServer`, body `…DeleteConfirmBody`.
  - Security policy: Remote MCP server URLs use HTTPS by default; `http://localhost`, `http://127.0.0.1`, and `http://[::1]` remain allowed. Toggle `settings.allowInsecureMcpHttp` (`settings.allowInsecureMcpHttpHint`) permits other local/network `http://` Remote MCP servers.

## AI Assistant

Section header `settings.sectionAiAssistant`. Owned by `src/modules/settings/AiSettings.tsx`. Per-provider configuration lives in `src/ai/providerRegistry/`.

- Provider picker; known-model picker is a real `<select>` showing every model — not an `<input list>`/`datalist` (Chromium hides non-matching options behind a `datalist`).
- OpenAI's curated recommendations replace GPT-5.5 with GPT-5.6 Luna, Terra, and Sol; Luna is the default. GPT-5.6 access is a limited preview and requires an approved OpenAI API organization. Grok's curated recommendations include `grok-4.5`.
- GitHub Copilot model refresh uses the signed-in account's Copilot CLI model catalog. The `settings.navigation.auto` model option leaves model choice to the Copilot runtime instead of sending a fixed model id; after a successful refresh, the picker shows `settings.navigation.auto` plus curated Copilot models that are also available to the signed-in account.
- Custom model ID is a separate text input.
- OpenAI Compatible providers can choose API request mode with `settings.apiMode`: `settings.apiModeChatCompletions` uses `/chat/completions`, and `settings.apiModeResponses` uses `/responses`.
- OpenAI Compatible providers can set `settings.extraHeaders` as comma-separated `key=value` pairs; example placeholder `settings.extraHeadersPlaceholder`. These headers are provider request metadata, not credential-backend secrets.
- API keys go into the selected credential backend under `AI_PROVIDER_SECRET_OWNER_ID`; never written to SQLite or settings JSON.
- Local Ollama uses the local server endpoint and does not show an API key field. Ollama Cloud is the Ollama provider that stores an API key.
- When a secret write to the credential backend fails (for example macOS Keychain access was denied), the save is reported as `settings.secretSaveFailed` and aborts before the provider settings persist, so the active provider does not change. Saving then opens the `settings.keychainSaveFailedTitle` recovery dialog (`ConfirmSheet`, `warn` tone) with body hint `settings.keychainResetHint`; its `settings.keychainResetAndRetry` action deletes the stored entries the draft is about to write and re-runs the save so the OS re-prompts for access. There is no deep link to a macOS keychain permission pane because keychain access is governed by the item ACL in Keychain Access.app, not by a System Settings privacy category.
- OpenAI exposes `settings.useCodexCli`; Anthropic exposes `settings.useClaudeCli`. When enabled, the API key entry is disabled and KKTerm delegates AI Assistant turns to a local CLI backend instead of the HTTP API-key provider path. KKTerm prefers the matching Agent Client Protocol stdio adapter, attaches the built-in `kkterm` MCP server for published safe tools such as Connection creation, then falls back to the vendor CLI's documented one-shot command mode if ACP is unavailable. The one-shot fallback is suggest-only for KKTerm tools. The setup row can check CLI install/auth status, start the matching Install Helper recipe (`codex-cli` or `claude-code-cli`) with missing prerequisites, and open the vendor auth command in an external terminal.
- CLI install/auth status checks are manual-only. The setup row persists the last manual result and shows its `settings.lastCheckedAt` timestamp when the user leaves and returns to Settings.
- Tool permission default (`ai.toolPermissionMode`) is set here as well.
- Assistant tools group: title `settings.aiToolsTitle`. It is collapsed by default; expand/collapse uses `common.expand` / `common.collapse`. Assistant tools default enabled, including `settings.aiTools.network.label` and `settings.aiTools.memory.label`, except `settings.aiTools.email.label`, which stays off until the user enables and configures delivery. The Tutorial tool is `settings.aiTools.tutorial.label` / `settings.aiTools.tutorial.description`. The Assistant memory tool (`settings.aiTools.memory.label` / `settings.aiTools.memory.description`) lets the assistant save and recall short durable notes about the user's hosts and preferences across chats; secrets are never stored as notes.
- Assistant Skills subgroup: title `settings.assistantSkillsTitle` (hint `settings.assistantSkillsHint`, empty `settings.assistantSkillsEmpty`). It is collapsed by default; expand/collapse uses `common.expand` / `common.collapse`. KKTerm copies missing bundled starter skills into the local app-data skills folder: `dashboard-widget-builder`, `dashboard-widget-designer`, `dashboard-data-visualization`, `desktop-accessibility-ui`, `dns-dhcp-troubleshooter`, `firewall-port-troubleshooter`, `network-connectivity-troubleshooter`, `remote-desktop-helper`, `sftp-transfer-helper`, `ssh-troubleshooter`, `terminal-command-planner`, and `tls-certificate-troubleshooter`. `settings.assistantSkillsOpenFolder` opens that folder where users add or edit one SKILL.md-compatible directory per skill. The Custom Skills row (`settings.assistantCustomSkillsTitle`, hint `settings.assistantCustomSkillsHint`) controls whether extra skill directories under `assistant-skills\custom` are included when the Assistant Skill list is refreshed and when the AI Assistant starts a request; `settings.assistantCustomSkillsOpenFolder` opens that folder. Per-row actions open that skill directory (`settings.assistantSkillsOpen`) and toggle whether the assistant can invoke it (`settings.assistantSkillsEnabled` / `settings.assistantSkillsDisabled`). Skill selection is model-driven through `assistant_use_skill`, not app keyword matching. v1 does not execute skill scripts.

## SSH

The SSH key generator accepts an optional passphrase plus confirmation (`settings.sshKeyPassphraseOptional`, `settings.sshKeyPassphraseConfirm`) and passes it to `ssh-keygen`; leaving it blank generates an unencrypted key.

Section header `settings.sectionSsh`. Default username, default identity file, agent forwarding, tmux defaults, etc. (Keep this section keyed under `settings.*` — exact field keys live in `en.json`.) The `connections.useTmux` row in Settings - SSH controls whether Add Connection defaults SSH Connections to tmux management; the per-Connection override lives in the add/edit Connection dialog's right-column SSH options. `settings.proxyJump` defines the default jump host for new SSH Connections. The SSH SOCKS proxy default moved to Settings → Proxy (`settings.proxy`): an SSH Connection that inherits defaults and has no per-Connection SOCKS override falls back to the global app proxy when it is a manual SOCKS5 endpoint (terminals, tmux, SFTP, and key transfer), dialed natively in-process with no external tools and never combined with ProxyJump. Per-Connection SSH SOCKS overrides remain in the add/edit Connection dialog under `connections.sshProxyOptions`, including `connections.sshSocksProxyUsernameOptional` and `connections.sshSocksProxyPasswordOptional` when Settings defaults are not inherited; inline `username:password@host:port` is accepted in the per-Connection address field. When `connections.inheritSettingsDefaults` is on in that dialog, ProxyJump and `connections.useTmux` show the current Settings defaults while the SOCKS fields stay blank so the launch uses the global app proxy; saving writes those displayed non-secret values into the saved Connection. Turning `connections.inheritSettingsDefaults` off makes those same fields editable and saves explicit per-Connection values; the per-Connection SOCKS proxy password is stored under that Connection's secret owner id rather than in SQLite. `settings.defaultTransparency` sets the starting SSH terminal transparency for new SSH Connections and Child Connection Tabs; the default is 50. `settings.randomDynamicBackgroundOnCreate` assigns a random dynamic terminal background only when creating new SSH Connections, new top-strip Tabs from SSH Connections, or new SSH Child Connection Tabs. SSH port forwarding mappings are edited from the SSH Pane dialog, not Settings.

The `settings.xServer` group controls the managed VcXsrv launcher. `settings.xServerManaged` starts VcXsrv before opening SSH Sessions when `vcxsrv.exe` is not already running and shows the Status Bar X indicator while the setting is enabled. The indicator reflects configuration, not command-based process polling. `settings.xServerPath` can override the executable path; blank uses standard VcXsrv install locations. `settings.xServerDisplay` chooses the local X display number, and `settings.xServerArgs` passes command-line flags. `settings.xServerLaunch` saves the current SSH Settings draft and starts VcXsrv immediately.

X11 forwarding is negotiated when a new native SSH Session starts. SSH Sessions that were already open before enabling or restarting VcXsrv need to be reconnected or opened again before remote X11 apps receive `DISPLAY`. Existing tmux panes can also keep an old shell environment; open a new tmux pane/window or export the new `DISPLAY` inside that shell.

## Terminal

Section header `settings.sectionTerminal`. Font family + size, line height, cursor style, scrollback length, bell behaviour, default shell on Local, and custom local shell profiles. Clipboard option `settings.copyOnSelect` copies a completed terminal selection through the same system-clipboard path as the explicit Copy command, for local and remote Sessions alike; toggling it takes effect immediately in already-open terminal Sessions. Its description `settings.copyOnSelectHint` explains that ordinary SSH selection copies immediately, tmux mouse mode requires Shift-selection (or disabling mouse mode), and tmux copy-mode selections do not trigger this option. The font family field (`settings.terminalFontFamily`) is grouped as Custom fonts, Recommended, then System fonts: user-dropped custom fonts (`settings.customFonts`) stay first, the platform-specific monospace list led by `settings.terminalFontDefault` follows inside `settings.recommendedFonts`, and OS-detected fonts (`settings.systemFonts`) come last. The default terminal font is a single CSS stack that resolves to each platform's native monospace via font fallback: Cascadia Mono on Windows, SF Mono on macOS, and the bundled JetBrains Mono on Linux (or anywhere the others are absent), so `settings.terminalFontDefault` names whichever the platform resolves. JetBrains Mono ships bundled with KKTerm and is therefore always offered as a Recommended terminal font on every platform, guaranteeing the stack renders even with no system monospace installed. macOS recommendations also include SF Mono and Menlo; Linux recommendations include Adwaita Mono, Ubuntu Mono, and common cross-distribution coding fonts; Windows retains Cascadia and Consolas choices. The refresh icon (`settings.refreshSystemFonts`) uses the same asynchronous shared refresh as Appearance, so activating either button rescans custom and system fonts, updates both pickers, and filters recommendations against the detected families without blocking initial render (status `settings.systemFontsRefreshed`, unavailable runtime `settings.systemFontsUnavailable`). Custom fonts are still managed from the app fonts folder, the shared hint is `settings.customFontsHint`, and the open-folder action is the icon-only `settings.openCustomFontsFolder` button. TTF/OTF files with the same internal family appear as one Custom fonts entry and contribute their available Regular, Bold, and Italic faces; missing faces do not prevent using the family. Nerd Font Normal, Mono, and Propo variants remain separate entries. App UI may use any variant, but Terminal restricts both the Custom fonts and System fonts groups to families whose metadata reports fixed-width (monospace) cells, so proportional faces never appear in the Terminal picker; an older saved proportional custom terminal family resets to the terminal default without changing other Terminal settings. The selected terminal font applies immediately to mounted local and SSH terminal Sessions: KKTerm refreshes xterm glyph metrics and refits the Pane without reconnecting. Custom fonts — including powerline/Nerd Fonts — render without a system-wide install because KKTerm loads them into the WebView itself; when asynchronous custom faces finish loading, mounted terminal Panes refresh again so fallback glyph metrics are not retained. The refreshed scanner prefers English metadata names so localized aliases in System fonts do not duplicate Recommended entries. The Custom shells subsection (`settings.customShells`) stores named command lines with optional arguments; the name field suggests common platform shells and fills a recommended command line that remains editable for non-default install paths. Saved entries appear in `settings.defaultShell` and in Add Connection → Local terminal → `connections.shell`. `settings.defaultTransparency` sets the starting local/Telnet/Serial terminal transparency for new local/Telnet/Serial terminal Connections and Child Connection Tabs; the default is 50. `settings.randomDynamicBackgroundOnCreate` assigns a random dynamic terminal background only when creating new local/Telnet/Serial Connections, new top-strip Tabs, or new Child Connection Tabs. `settings.terminalColorScheme` (hint `settings.terminalColorSchemeHint`) uses an app-owned scrollable listbox containing the bundled 117-scheme catalog. The selected control and every option use that scheme's real terminal background and foreground colors; keyboard users open the list and navigate it with Up/Down, Home, End, Enter, and Escape. The catalog combines KKTerm's original palettes with all 112 TerminalColors variants, deduplicating the 17 already represented; scheme names are proper nouns and stay untranslated. Each terminal-type Connection can override the global choice from the terminal Pane actions menu (`terminal.colorScheme`) — the override is stored on the durable Connection record and deliberately does not appear in the add/edit Connection dialog. The Integrations subsection (`settings.terminalIntegrations`, hint `settings.terminalIntegrationsHint`) holds `settings.enableInlineImages` (`settings.enableInlineImagesHint`), enabling the Sixel / iTerm2 inline image protocols for newly opened terminals, and `settings.allowTerminalNotifications` (`settings.allowTerminalNotificationsHint`), surfacing OSC 9 / OSC 777 program notifications through the Status Bar; turning notifications off silences already-open terminals immediately. The Hyperlink rules subsection (`settings.hyperlinkRules`, hint `settings.hyperlinkRulesHint`) stores regex → URL rules (`settings.hyperlinkRulePattern`, `settings.hyperlinkRuleUrl`; add via `settings.addHyperlinkRule`, remove via `settings.removeHyperlinkRule`) that turn matching terminal text into Ctrl+click links. `$0`–`$9` in the URL substitute capture groups, URLs must be http(s) (`settings.hyperlinkRuleUrlInvalid`), half-filled rows fail with `settings.hyperlinkRuleIncomplete`, and non-compiling patterns fail with `settings.hyperlinkRuleInvalidPattern`. Rules apply to newly opened terminal Panes.

## RDP and VNC

- `settings.sectionRdp` — RDP defaults: `settings.remoteDesktopViewMode`, resolution, colour depth, redirection toggles.
- `settings.sectionVnc` — VNC defaults: `settings.remoteDesktopViewMode`, colour depth, view-only, encoding preferences. The view-mode default controls how new or inheriting VNC Connections display large or multi-monitor framebuffers before a per-Connection override is selected from the remote desktop toolbar.

## URL

`settings.sectionUrl` — defaults for URL Connections. The proxy default moved to Settings → Proxy (`settings.proxy`); URL Tabs that inherit defaults follow that global app proxy, and a per-Connection override still wins. `settings.urlDataShards` manages URL data shard labels and includes the global default shard used by URL Connections that inherit Settings defaults. `settings.urlUserAgent` sets an optional global default user-agent string for URL Connections; blank keeps the platform webview default, and individual URL Connections can override it in `connections.urlOptions`. `settings.urlSavedPasswords` can show multiple saved password/input-data entries for the same URL Connection when a site uses multi-page authentication; each entry is keyed by the page origin and path, with temporary query strings and fragments ignored. Each record keeps its Connection name, truncated page URL, Edit, and Delete controls on one row. Edit opens the shared compact editor dialog instead of expanding an inline form. Each editor row shows the captured field's exact selector and matching-element occurrence beside its value. The saved primary password starts masked and has an eye control; non-password values start visible and have a lock control that persists whether the editor masks them next time, plus an eye control for temporary reveal while masked. Masking a non-password value changes only its editor presentation and does not move that SQLite value into the credential backend. Settings → Credentials renders the same records and controls through the same component. A URL Connection may inherit these defaults, force direct access, or store its own endpoint and shard from the add/edit Connection dialog's right-column `connections.urlOptions`. HTTP mode carries both HTTP and HTTPS destinations; authenticated proxies, PAC files, and bypass lists are outside Tauri's per-WebView proxy API. macOS requires version 14 or later. URL Connections use stable owned overlay windows, not Tauri's `unstable` child-webview API. The `unstable` child-webview path was removed because it changed the main app WebView2 host shape and could break terminal keyboard input after Alt+Tab/app switch or minimize/restore until the user clicked the terminal Pane again.

## Proxy

Section header `settings.proxy` (rendered without a section-header glyph, following the Settings page convention). This is a top-level Settings section in the left sidebar, listed above About, and is reached with `tutorial_highlight` target `settings.proxy` (navigation `page=settings settingsSectionId=proxy-settings`).

- Subsection `settings.proxy` (hint `settings.proxyHint`): the global network proxy for all KKTerm activity — connections, app updates, AI providers, and other web requests. `settings.proxyMode` selects `settings.proxyModeSystem` (follow the operating system proxy: Windows WinINET, macOS CFNetwork, Linux environment variables), `settings.proxyModeNone` (force a direct connection), or `settings.proxyModeManual`. Manual mode shows `settings.proxyProtocol` (`settings.proxyHttp`, `settings.proxyHttps`, `settings.proxySocks5`), `settings.proxyHost` (placeholder `settings.proxyHostPlaceholder`), and `settings.proxyPort`. Per `settings.proxyPlatformHint`, a manual SOCKS5 proxy also routes SSH/SFTP and Telnet sessions, while HTTP/HTTPS proxies apply to web and app requests only. The proxy applies on next request/Session start; URL Tabs and reqwest activities pick it up when they next open. Authenticated proxies, PAC files, and bypass lists are not configured here.
- Save status: `settings.proxySettingsSaved`. The proxy mode and manual endpoint persist into the General settings record (`proxyMode` / `proxyUrl`) even though the controls now live in this dedicated section.

## About

`settings.sectionAbout`. Shows version (`settings.version`) and slogan (`settings.appSlogan`). The version value should match `package.json`'s `version` field. License info, GitHub link, and acknowledgements live here.

Manual app update checks live in General -> `settings.softwareUpdates`, not About. `settings.autoUpdateChecks` controls startup update checks, and manual checks surface update state through `settings.checkingForUpdates`, `settings.updateNoUpdates`, and `settings.updateCheckFailed`. When an app update is available, the `settings.updatePromptLabel` dialog shows `settings.updateAvailableBody`, renders `settings.updateNotes` from the release markdown or updater metadata, and offers `settings.updateOpenDownloadPage`, `settings.updateDownloadAndInstall`, or `settings.updateLater` when an installable update is available for the current platform. Download and install replaces the prompt with the shared determinate Status Bar popup, driven by actual downloaded bytes. On Windows, its close button uses `settings.updateDownloadCancel` to stop the active transfer and delete the partial installer; after checksum verification, the popup stays at 100% for three seconds, then KKTerm exits and launches the installer. When the installer exits successfully, the detached handoff deletes that downloaded installer and removes the empty update directory; a failed or cancelled installer is retained. On macOS and Linux, the signed Tauri updater reports real progress and follows the same three-second completion delay before installation and relaunch; the current updater API does not expose reliable in-flight cancellation, so it does not show a cancel control while downloading.


## Built-in MCP Server

- Location: Settings → AI Assistant section on Windows, macOS, and Linux. The bridge transport is a named pipe on Windows and a `0600` Unix domain socket on macOS/Linux; the built-in MCP rows are shown on all three.
- Toggle keys: `settings.builtInMcpServerEnabled` (`settings.builtInMcpServerEnabledHint`) and `settings.builtInMcpAllowAllDangerous` (`settings.builtInMcpAllowAllDangerousHint`).
- Config dialog keys: `settings.builtInMcpShowConfig`, `settings.builtInMcpConfigTitle`, `settings.builtInMcpConfigIntro`, `settings.builtInMcpConfigFormatJson`, `settings.builtInMcpConfigFormatToml`, `settings.builtInMcpConfigCopy`, `settings.builtInMcpConfigCopied`, `settings.builtInMcpConfigLocationsTitle`, `settings.builtInMcpConfig*Header`, and `settings.builtInMcpConfigMethod*`.
- Config dialog behavior: opens only when the user activates `settings.builtInMcpShowConfig`; changing either MCP toggle never opens the dialog. It shows copyable JSON (`mcpServers.kkterm`) and TOML (`[mcp_servers.kkterm]`) snippets for stdio MCP clients using the resolved `kkterm-cli` path beside the running KKTerm executable (`kkterm-cli.exe` on Windows). The setup table shows localized Agent/Method/Project/Global headings. Codex and Claude Code rows include documented CLI commands where supported; VS Code/GitHub Copilot, Antigravity, and OpenCode rows use `settings.builtInMcpConfigMethodManualEdit` and list config locations.
- Purpose: enable/disable the local built-in MCP server surface and control whether built-in MCP tools with a `dangerous` namespace segment, such as `kkterm.workspace.quick_commands.dangerous.create`, require confirmation prompts or run in allow-all mode.
- Debug logging: debug builds write built-in and remote MCP request/response records to `mcp.debug.log` beside `kkterm.log`; release builds write the same MCP log when `settings.advancedDebugging` is enabled. Built-in MCP logging redacts terminal send input, terminal buffer reads, Dashboard widget source/body JSON, and secret-looking argument fields before writing debug records.
