# Profiles
par-term provides a profile system for saving and quickly launching shells with custom configurations, similar to iTerm2's profile system.
## Table of Contents
- [Overview](#overview)
- [Profile Settings](#profile-settings)
- [Managing Profiles](#managing-profiles)
- [Settings UI](#settings-ui)
- [Open Profiles](#open-profiles)
- [Profiles Drawer](#profiles-drawer)
- [Profile Shortcuts](#profile-shortcuts)
- [Creating Profiles](#creating-profiles)
- [Profile Icon Picker](#profile-icon-picker)
- [Using Profiles](#using-profiles)
- [Which Profile a Tab Runs](#which-profile-a-tab-runs)
- [Auto-Switching](#auto-switching)
- [Directory-Based Profile Switching](#directory-based-profile-switching)
- [Tmux Profile Auto-Switching](#tmux-profile-auto-switching)
- [par-mux Session-Based Switching](#par-mux-session-based-switching)
- [Hostname-Based Switching](#hostname-based-switching)
- [Auto-Switch Priority](#auto-switch-priority)
- [Auto-Switch Visual Application](#auto-switch-visual-application)
- [Profile Commands and Confirmation](#profile-commands-and-confirmation)
- [Tmux Auto-Connect](#tmux-auto-connect)
- [par-mux Auto-Attach](#par-mux-auto-attach)
- [Default Startup Directory](#default-startup-directory)
- [Per-Profile Badge Configuration](#per-profile-badge-configuration)
- [Per-Profile Shader Settings](#per-profile-shader-settings)
- [Per-Pane Background Settings](#per-pane-background-settings)
- [Available Controls](#available-controls)
- [Darken Control](#darken-control)
- [Real-Time Preview](#real-time-preview)
- [Settings UI](#settings-ui-1)
- [Dynamic Profiles](#dynamic-profiles)
- [Configuration](#configuration-1)
- [Background Refresh](#background-refresh)
- [Local Cache](#local-cache)
- [Conflict Resolution](#conflict-resolution)
- [Security](#security)
- [Visual Indicators](#visual-indicators)
- [Keybinding](#keybinding)
- [Dynamic Profiles Settings UI](#dynamic-profiles-settings-ui)
- [Storage](#storage)
- [Related Documentation](#related-documentation)
## Overview
Profiles allow you to save terminal configurations for quick access:
```mermaid
graph TD
Profiles[Profile System]
Manager[ProfileManager]
Drawer[Open Profiles / Profiles Drawer]
Modal[Settings > Profiles]
Storage[profiles.yaml]
Session[Tab, Window, or Split]
Profiles --> Manager
Manager --> Drawer
Manager --> Modal
Manager --> Storage
Drawer -->|open_profile actions| Session
Modal -->|Create/Edit| Manager
style Profiles fill:#e65100,stroke:#ff9800,stroke-width:3px,color:#ffffff
style Manager fill:#1b5e20,stroke:#4caf50,stroke-width:2px,color:#ffffff
style Drawer fill:#0d47a1,stroke:#2196f3,stroke-width:2px,color:#ffffff
style Modal fill:#4a148c,stroke:#9c27b0,stroke-width:2px,color:#ffffff
style Storage fill:#37474f,stroke:#78909c,stroke-width:2px,color:#ffffff
style Session fill:#880e4f,stroke:#c2185b,stroke-width:2px,color:#ffffff
```
## Profile Settings
Each profile can customize the following:
| Setting | Description | Required |
|---------|-------------|----------|
| **Name** | Display name for the profile | Yes |
| **Icon** | Nerd Font icon or custom text identifier | No |
| **Working Directory** | Initial directory for the tab | No |
| **Command** | Custom command (instead of default shell) | No |
| **Command Arguments** | Arguments for the custom command | No |
| **Tab Name** | Custom name for the terminal tab | No |
| **Shell** | Specific shell for this profile (overrides global) | No |
| **Login Shell** | Override global login shell setting (None/true/false) | No |
| **Tags** | Comma-separated tags for organization and filtering | No |
| **Parent Profile** | Inherit settings from another profile | No |
| **Keyboard Shortcut** | Records the chord bound to this profile's `open_profile:<id>` keybinding (see [Profile Shortcuts](#profile-shortcuts)) | No |
| **SSH Host** | SSH hostname for remote connections | No |
| **SSH User** | SSH username | No |
| **SSH Port** | SSH port number | No |
| **SSH Identity File** | Path to SSH identity/key file | No |
| **SSH Extra Args** | Additional SSH command-line arguments | No |
| **Hostname Patterns** | Glob patterns for SSH-based auto-switching | No |
| **Directory Patterns** | Glob patterns for CWD-based auto-switching | No |
| **Tmux Session Patterns** | Glob patterns for auto-switching (e.g., `work-*`) | No |
| **Tmux Session** | tmux session to auto-connect when this profile opens (uses create-or-attach) | No |
| **Tmux Mode** | Connection mode: Control Mode (full integration) or Normal (plain tmux in PTY) | No |
| **par-mux Session Patterns** | Glob patterns for auto-switching when the window attaches to a matching par-mux session | No |
| **par-mux Session** | par-mux session to create-or-attach when this profile opens (see [par-mux Auto-Attach](#par-mux-auto-attach)) | No |
| **Badge Text** | Custom badge format for this profile | No |
| **Badge Appearance** | Override badge color, font, position, size | No |
| **Background Shader** | Custom shader path/name override | No |
| **Shader Brightness** | Shader brightness override | No |
| **Shader Text Opacity** | Shader text opacity override | No |
| **Shader Animation Speed** | Shader animation speed override | No |
| **Shader Textures** | Custom iChannel0-3 texture set override | No |
## Managing Profiles
### Settings UI
Profile management is embedded in the Settings window under the **Profiles** tab. Open Settings (`F12` or `Cmd/Ctrl + ,`) and navigate to the Profiles tab.
**Profile Management Features:**
- Create, edit, delete, and reorder profiles inline
- Up/Down buttons to change profile order
- Edit (pencil) and Delete (trash) buttons per profile
- Unsaved changes indicator
**Profiles › Manage Profiles...** in the menu bar, the Profiles drawer's **Manage** button, the launcher's row menu, and the `manage_profiles` action (command palette: **Manage Profiles**) all open the Settings window to the Profiles tab.
### Open Profiles
**Open Profiles…** is one keyboard-first launcher for every profile (iTerm2's Open Profiles). It replaced the tab bar's old "New Tab" profile window.
**Opening it:**
- Press `Cmd+O` (macOS). On Windows/Linux it ships unbound: use the **Profiles** menu, the command palette, or bind `toggle_profile_drawer`
- Click the chevron next to the tab bar's `+` button
- With `new_tab_shortcut_shows_profiles: true`, the new-tab shortcut opens it
**Keys:**
| Key | Action |
|-----|--------|
| type | Filter by profile name or tag |
| `↑` `↓` `PgUp` `PgDn` `Home` `End` | Move the selection |
| `Enter` | Open the profile in a new tab |
| `Shift+Enter` | Open it in a new window |
| `Cmd+D` / `Cmd+Shift+D` | Split the focused pane right / down, running the profile |
| `Cmd+Enter` | Give the active tab this profile (and pin it) |
| `Ctrl+Space` | Mark the row; an activation with marked rows opens every marked profile |
| `Esc` or the toggle chord | Close |
Each row shows the profile's live keybinding (its `open_profile:<id>` chord), its tags, and a **dynamic** marker for profiles from a remote source. The first row, **Default**, is a plain tab running your configured shell. Click a tag chip to show only that tag. Right-click a row for **Open in** (New Tab, New Window, Split Right, Split Down, This Tab), **Edit Profile…**, and **Duplicate**.
A split with a profile works in local tabs. A par-mux or tmux pane cannot start a profile's program yet (the daemon's `split-window` takes a directory but no command), so the launcher says so instead of opening a pane that ignores the profile.
### Profiles Drawer
The Profiles drawer is Open Profiles pinned to the right edge of the window: the same list, keys, and actions. The terminal reflows beside it rather than drawing under it.
**Opening the drawer:**
- Click the toggle button on the right edge of the window,
- Choose **View › Profiles Panel** in the menu bar (checked while the drawer is open), or
- Bind `toggle_profiles_panel`
The drawer takes keys only while its filter has focus, so typing in the terminal never moves its selection. `Esc` in the filter, or its **✕** button, closes it.
### Profile Shortcuts
A profile shortcut is an ordinary keybinding to `open_profile:<id>`. Record it in the profile editor's **Keyboard Shortcut** field (General sub-tab): **Record** captures a chord and **Clear** removes it. Done writes the profile's one `open_profile:<id>` binding, replacing any previous chord rather than adding a second, and Settings' Save persists it. You can also bind it in **Settings › Keys › Key Bindings** like any other action. Either way it is conflict-checked against every other chord and shows in the command palette and the launcher.
The older per-profile **Keyboard Shortcut** field is migrated on first launch: each profile's shortcut becomes an `open_profile:<id>` binding with the same chord, and the field is cleared. A shortcut that does not parse, or whose chord another binding already holds, is left on the profile and logged; bind it by hand. A child profile no longer inherits its parent's shortcut.
Related actions: `open_profile_window:<id>`, `split_profile:<id>:right`, `split_profile:<id>:down`, and `set_tab_profile:<id>` (see [Keyboard Shortcuts](../guides/KEYBOARD_SHORTCUTS.md)).
## Creating Profiles
**Step-by-step:**
1. Open Settings › Profiles (**Profiles › Manage Profiles...** in the menu bar, the drawer's **Manage** button, or **Manage Profiles** in the command palette)
2. Click **+ New Profile**
3. Fill in the profile settings:
- **Name** (required): Give your profile a descriptive name
- **Icon**: Add a Nerd Font icon for visual identification
- **Working Directory**: Set the starting directory
- **Command**: Override the default shell (optional)
- **Arguments**: Space-separated command arguments
- **Tab Name**: Custom tab title (optional, on the Text & Badge sub-tab)
4. Optionally click the icon picker button to choose a Nerd Font icon
5. Click **Done** to return to the profile list
6. Click **Save** at the bottom of the Settings window. It writes profile and configuration changes together; **Revert** drops them
### Profile Icon Picker
The profile icon field includes an icon picker popup with ~200 curated Nerd Font icons organized in 14 categories. Nerd Font icons render reliably in the egui-based settings UI and each icon shows a descriptive tooltip on hover.
| Category | Description | Example Icons |
|----------|-------------|---------------|
| Terminal | Shells and terminal emulators | Terminal, Bash, PowerShell, tmux, Prompt |
| Dev & Tools | Languages and development tools | Code, GitHub, Python, Rust, TypeScript, Go, C/C++ |
| Files & Data | Files, folders, and storage | File, Folder, Database, Save, Package |
| Network & Cloud | Networking and cloud services | Globe, WiFi, Cloud, Server, SSH, AWS |
| Security | Locks, keys, and access control | Lock, Shield, Key, Eye, Warning |
| Git & VCS | Version control systems | Branch, Merge, Commit, GitHub, GitLab, BitBucket |
| Weather & Nature | Weather and natural elements | Sun, Moon, Snowflake, Lightning, Rainy, Tree, Leaf |
| Containers & Infra | Containers and infrastructure | Docker, Kubernetes, CPU, Gear, Memory |
| OS & Platforms | Operating systems and platforms | Apple, Windows, Linux, Android, Homebrew |
| Status & Alerts | Status indicators and signals | Check, Bolt, Rocket, Fire, Star |
| UI Actions | Common interface actions | Search, Edit, Copy, Plus, Refresh, Save |
| Navigation | Arrows and directional icons | Arrow Up/Down, Angle Left/Right, Reply |
| People & Misc | People and miscellaneous symbols | User, Robot, Gamepad, Music, Bookmark |
| Fun & Seasonal | Seasonal and fun symbols | Ghost, Skull, Gift, Magic Wand, Sparkle, Trophy |
Click any icon to set it as the profile icon, or type a custom value directly in the text field. Use the "Clear icon" button to remove the current icon.
**Example Profiles:**
| Profile | Command | Working Dir | Use Case |
|---------|---------|-------------|----------|
| Development | - | `~/projects` | General development |
| SSH Server | `ssh user@server` | - | Remote connection |
| Docker Shell | `docker exec -it container bash` | - | Container access |
| Python REPL | `python3` | `~/scripts` | Interactive Python |
## Using Profiles
**Launch a Profile:**
1. Open Profiles (`Cmd+O` on macOS, the tab bar chevron, or the Profiles menu)
2. Type part of its name or a tag
3. Press `Enter` (new tab), `Shift+Enter` (new window), or `Cmd+D` / `Cmd+Shift+D` (split)
The command palette lists four rows per profile: **Open Profile**, **Open Profile in New Window**, **Split with Profile**, and **Change Tab Profile**.
**What Happens:**
- A new tab opens with the profile's configuration
- Working directory is set if specified
- Custom command runs (or default shell if not specified)
- Tab name updates if specified
**Splits and restarts keep the profile's program:**
- Splitting a profile tab runs the same program in the new pane: the profile's SSH connection, command, or shell. The new pane starts in the focused pane's directory. Turn this off with `split_inherits_profile: false` (Settings > Panes > Layout & Dividers > "Splits run the tab's profile program") to get the default shell instead.
- A profile that attaches a tmux or par-mux session is not inherited, since its program would attach again. Splits of those tabs, and of par-mux tabs, work as usual.
- **Restart Pane** (`restart_pane`) reruns the program the pane was started with, so a profile tab's first pane restarts its SSH connection or command rather than a local shell. So do the `shell_exit_action` restart options.
- An SSH connection typed by hand, or opened with SSH Quick Connect (which types `ssh` into the current shell), is not a profile program: a split of that tab starts a local shell.
## Which Profile a Tab Runs
A tab remembers the profile it was opened from, and any profile an automatic switch applied on top of it:
- **Tab tooltip:** hover a tab for `Profile: Work`, or `Profile: Prod (auto: host prod.example.com)` while an automatic switch is applied.
- **Profile status-bar widget:** the active tab's profile name. It ships off; turn it on in Settings › Status Bar.
- **Variables:** `\(tab.profile_name)` in a badge or status-bar format is the active tab's profile (`Default` for a plain tab); `\(session.profile_name)` follows the active tab too.
- **Change it:** **Change Profile…** on the tab's context menu, `Cmd+Enter` in Open Profiles, or **Change Tab Profile: X** in the palette. This applies the profile's icon, title, badge, and shader to the tab (the running process is not replaced) and pins the tab.
- **Edit it:** **Session › Edit Tab's Profile...** in the menu bar, or the `edit_tab_profile` action, opens Settings › Profiles and names the tab's profile in a toast.
## Default Startup Directory
When opening a new terminal without a profile, par-term uses the configured startup directory mode.
### Startup Modes
| Mode | Description |
|------|-------------|
| `home` | Start in home directory (default) |
| `previous` | Start in the last used working directory |
| `custom` | Start in a user-specified directory |
### Configuration
```yaml
# Startup mode: "home", "previous", or "custom"
startup_directory_mode: "home"
# Custom directory (only used when mode is "custom")
startup_directory: "/path/to/directory"
```
### Settings UI
1. Press `F12` to open Settings
2. Navigate to **Terminal** → **Shell**
3. Find the **Startup Directory** section
4. Select mode and configure path if needed
### Priority
Directory selection follows this priority:
1. **Profile working directory** - If launching a profile with a directory set
2. **Legacy `working_directory`** - If set in config (for backwards compatibility)
3. **Startup directory mode** - Based on `startup_directory_mode` setting
4. **Home directory** - Fallback if configured path doesn't exist
> **📝 Note:** The `previous` mode requires shell integration to track directory changes while the shell runs.
## Auto-Switching
par-term can automatically apply profiles based on the current working directory, tmux session name, or remote hostname. Auto-switched profiles apply all visual settings including icon, title, badge, and optional command execution.
### Directory-Based Profile Switching
Profiles can automatically apply when the terminal's working directory matches configured glob patterns.
**Configuration:**
Add `directory_patterns` to a profile:
```yaml
- id: 550e8400-e29b-41d4-a716-446655440000
name: Work Projects
directory_patterns:
- "~/Repos/work-*"
- "~/Repos/company-*"
- "/opt/projects/*"
icon: "🏢"
badge_text: "WORK"
```
**Pattern Examples:**
| Pattern | Matches |
|---------|---------|
| `~/Repos/work-*` | `~/Repos/work-api`, `~/Repos/work-frontend` |
| `/opt/projects/*` | Any directory under `/opt/projects/` |
| `~/Repos/par-term*` | `~/Repos/par-term`, `~/Repos/par-term-core` |
- Patterns support `~` for home directory expansion
- CWD changes are detected via OSC 7 (requires shell integration)
- First matching profile wins (check profile order)
- Profile clears when CWD no longer matches any pattern
**Settings UI:**
1. Open Settings > Profiles
2. Edit a profile
3. Open the **Auto-Switch** sub-tab
4. Enter comma-separated glob patterns in the **Directories** field
### Tmux Profile Auto-Switching
Profiles can automatically apply when connecting to tmux sessions with matching names.
**Configuration:**
Add `tmux_session_patterns` to a profile:
```yaml
- id: 550e8400-e29b-41d4-a716-446655440000
name: Production
tmux_session_patterns:
- "*-prod"
- "*-production"
- "prod-*"
badge_text: "🔴 PROD"
badge_color: [255, 0, 0]
```
**Pattern Matching:**
| Pattern | Matches |
|---------|---------|
| `dev-*` | `dev-api`, `dev-frontend`, etc. |
| `*-prod` | `api-prod`, `web-prod`, etc. |
| `*server*` | `webserver`, `api-server-1`, etc. |
| `main` | Exact match only |
- Patterns are case-insensitive
- First matching profile wins (check profile order)
- Profile clears when tmux session ends
**Settings UI:**
1. Open Settings > Profiles
2. Edit a profile
3. Open the **Auto-Switch** sub-tab
4. Enter comma-separated patterns in the **tmux sessions** field: `work-*, *-production`
### par-mux Session-Based Switching
The par-mux analogue of the tmux rule: when the window attaches to a par-mux session — via the session picker, a profile's `mux_session_name` auto-connect, or the `mux_auto_attach` launch option — profiles with a matching `mux_session_patterns` entry apply to the attached tab.
```yaml
profiles:
- name: Production
mux_session_patterns:
- "*-prod"
- "PARMux"
```
Patterns are comma-separated globs in the **par-mux sessions** field of the Auto-Switch sub-tab, matched case-insensitively; the first matching profile wins (profile order decides). A pinned active tab keeps its profile, and opening a profile explicitly (which pins the tab) is never overridden by the rule.
### Hostname-Based Switching
Profiles automatically apply when connecting to remote hosts with matching hostnames, detected via OSC 7 shell-integration sequences (`file://hostname/path`). Hostname patterns are matched against the host extracted from the OSC 7 URL; the local host is ignored. Enter them in the **Hosts** field of the profile editor's Auto-Switch sub-tab.
### Auto-Switch Priority
When multiple auto-switch mechanisms could apply, the following priority order determines which profile wins:
1. **Explicit user selection** — a tab given a profile with Change Tab Profile, or pinned, never switches automatically
2. **Hostname match** — remote host detection via OSC 7 (an SSH session reports its host this way; highest auto priority)
3. **Directory match** — CWD-based matching via OSC 7
4. **Tmux session match** — tmux session name pattern matching (applied via the tmux gateway separately)
5. **par-mux session match** — par-mux session name pattern matching (applied at attach time; same independence as the tmux rule)
Tmux session matching runs independently through the gateway tab and does not compete with hostname or directory switching. par-mux session matching runs at attach time on the attached tab.
Every tab is evaluated, not only the one you are looking at: a background tab that connects to a matching host switches too.
**Announced and undoable.** Each switch shows a toast — `Profile Prod applied (host prod.example.com)` — with an **Undo** button. Undo reverts the tab and does not re-apply that profile until its rule stops matching (you leave the host or directory).
**Pin a tab** to keep automatic switching away from it: **Pin / Unpin Profile** on the tab's context menu, **Session › Pin Profile** in the menu bar (checked while the active tab is pinned), or the `toggle_tab_profile_pin` action. Changing a tab's profile by hand pins it too.
### Auto-Switch Visual Application
When a profile is auto-applied via any switching mechanism (directory, hostname, tmux session, or par-mux session), the following settings are applied to that tab:
| Setting | Description |
|---------|-------------|
| **Profile icon** | Displayed in the tab bar (horizontal and vertical layouts) |
| **Tab title** | Overrides the current tab title |
| **Badge text** | The tab's badge; it follows the tab, so switching tabs switches badges |
| **Badge styling** | Applies badge color, alpha, font, bold, margins, size while the tab is active |
| **Command** | Queues the profile's command for confirmation (if configured), aimed at the switched tab — see [Profile Commands and Confirmation](#profile-commands-and-confirmation) |
The tab's original title, icon, and badge are saved when an auto-profile applies and restored when it clears or is undone.
### Profile Commands and Confirmation
A profile's `command` is written into the running shell, and the thing that triggers an auto-switch is an OSC 7 sequence — which is emitted by whatever is producing terminal output, including a remote host you are SSH'd into. A `*` hostname pattern matches everything. Auto-switch therefore **never executes a profile command inline**. The command is queued in the same confirmation queue that trigger `RunCommand` and `SendText` actions use, so you see the exact command text before anything runs.
Two rules sit on top of that queue:
- **`ssh.ssh_auto_profile_switch`** gates hostname-driven switching entirely. With it off, a remote host cannot cause a profile switch at all.
- **A profile fetched from a dynamic source re-confirms every time**, even if you previously chose "Always Allow" for that exact command. Consenting to a profile *source* is not consent to arbitrary commands from it, and the source can change the command on any refresh. Local profiles do honour an earlier "Always Allow".
The approval is keyed on both the profile and the command text, so an "Always Allow" granted for one command does not carry over when the profile is edited or re-fetched with a different one. Profile-command approvals are also kept in a separate identifier space from trigger approvals, so a grant cannot leak between the two systems.
## Tmux Auto-Connect
Profiles can automatically connect to a named tmux session when opened. This is separate from the global `tmux_auto_attach` startup option — per-profile sessions let different profiles connect to different named sessions.
### Configuration
Set `tmux_session_name` on a profile to enable auto-connect. The profile uses **create-or-attach** semantics (`tmux new-session -A -s <name>`), so opening the profile either creates the session if it doesn't exist or attaches to it if it does.
```yaml
profiles:
- name: Work
tmux_session_name: work-session
tmux_connection_mode: control_mode # or: normal
```
### Connection Modes
| Mode | YAML value | Behavior |
|------|-----------|----------|
| **Control Mode** (default) | `control_mode` | Full par-term integration via `tmux -CC`. Enables pane sync, window tabs, and input routing. |
| **Normal** | `normal` | Plain tmux UI runs in the PTY. No par-term integration. |
### UI
In the profile editor (Settings → Profiles), the **Tmux Auto-Connect** collapsible section appears on the **Session** sub-tab:
- **Session Name** — leave empty to disable auto-connect
- **Connection Mode** — radio buttons for Control Mode vs Normal
### Behavior
- Auto-connect only fires when `tmux_enabled = true` in global config
- If the window is already connected to tmux (gateway active), the auto-connect is skipped silently
- Errors are logged via the debug log (`make tail-log`)
## par-mux Auto-Attach
Set `mux_session_name` on a profile to create-or-attach a par-mux daemon session when the profile opens. Sessions keep running in the daemon after par-term closes.
```yaml
profiles:
- name: Work
mux_session_name: work
```
In the profile editor, the **par-mux Auto-Attach** section on the **Session** sub-tab has a **Session Name** field (empty disables it). The name may not contain spaces, quotes, or backslashes, because the daemon command grammar has no quoting.
## Per-Profile Badge Configuration
Profiles can override global badge settings for visual differentiation per environment.
### Available Overrides
| Setting | Description |
|---------|-------------|
| `badge_text` | Custom badge format string |
| `badge_color` | RGB color override |
| `badge_color_alpha` | Opacity override (0.0-1.0) |
| `badge_font` | Font family override |
| `badge_font_bold` | Bold toggle override |
| `badge_top_margin` | Position override |
| `badge_right_margin` | Position override |
| `badge_max_width` | Size constraint override |
| `badge_max_height` | Size constraint override |
### Example: Environment Indicators
```yaml
# Production profile - red badge
- name: Production
badge_text: "🔴 PROD"
badge_color: [255, 0, 0]
badge_color_alpha: 0.3
# Development profile - green badge
- name: Development
badge_text: "🟢 DEV"
badge_color: [0, 255, 0]
badge_color_alpha: 0.2
# Staging profile - yellow badge
- name: Staging
badge_text: "🟡 STAGING"
badge_color: [255, 200, 0]
```
### Settings UI
1. Open profile editor (double-click profile or click edit)
2. Expand "Badge Appearance" section
3. Check boxes to enable individual overrides
4. Configure color, font, margins, and size as needed
## Per-Profile Shader Settings
Profiles can override the global background shader, allowing different visual effects per environment.
### Available Overrides
| Setting | Description |
|---------|-------------|
| `shader` | Shader path or name override |
| `shader_brightness` | Brightness adjustment override |
| `shader_text_opacity` | Text opacity override |
| `shader_animation_speed` | Animation speed override |
| `shader_texture_set` | Custom iChannel0-3 texture set (array of 4 optional paths) |
### Example
```yaml
- name: Presentation
shader: "aurora"
shader_brightness: 0.8
shader_text_opacity: 0.9
```
See [Custom Shaders](CUSTOM_SHADERS.md) for the full shader system documentation.
## Per-Pane Background Settings
When using split panes, each pane can have its own custom background image that overrides the global background. Per-pane backgrounds support independent image selection, display mode, opacity, and darkening control.
### Available Controls
| Setting | Description | Range |
|---------|-------------|-------|
| **Background Image** | Custom image path for this pane | — |
| **Display Mode** | How the image fills the pane (fit, fill, stretch, tile, center) | — |
| **Opacity** | Transparency of the background image | 0.0–1.0 |
| **Darken** | Darkens the background by reducing RGB towards black, independent of opacity | 0.0–1.0 |
### Darken Control
The darken slider (0.0–1.0) reduces the RGB values of the background image towards black while leaving opacity unchanged. This allows you to dim a bright background without affecting its transparency level:
- **0.0** — No darkening applied (full brightness)
- **0.5** — Background is 50% darkened (RGB values reduced by half)
- **1.0** — Fully darkened to black
For example, a background with `opacity: 0.8` and `darken: 0.5` will be 80% opaque and 50% darker than the original image.
### Real-Time Preview
Per-pane background settings apply instantly as values change. Adjusting the image, mode, opacity, or darken level immediately updates the preview in the terminal. No manual "Apply" button is required — changes take effect in real-time.
### Example: Production vs. Development Panes
```yaml
pane_backgrounds:
# Left pane: production environment with dim red overlay
- index: 0
image: "~/images/prod-bg.png"
mode: fill
opacity: 0.7
darken: 0.3
# Right pane: development environment with bright blue overlay
- index: 1
image: "~/images/dev-bg.png"
mode: fit
opacity: 0.6
darken: 0.0
```
### Settings UI
Access per-pane background settings in **Settings > Panes > Pane Backgrounds**:
1. Click on a split pane in the preview (if using split panes)
2. Configure the following for the selected pane:
- **Image**: Browse to and select a custom background image, or leave empty to use the global background
- **Mode**: Choose how the image fills the pane
- **Opacity**: Adjust the transparency slider (0.0–1.0)
- **Darken**: Adjust the darkening slider (0.0–1.0)
Changes apply immediately to the terminal without requiring manual confirmation.
## Dynamic Profiles
par-term can fetch profiles from remote URLs, enabling teams to share standardized terminal configurations. Dynamic profiles are read-only and update automatically in the background.
```mermaid
graph TD
Sources[Remote Sources]
Fetch[Background Fetch]
Cache[Local Cache]
Merge[Profile Merger]
Local[Local Profiles]
Combined[Combined Profile List]
Sources --> Fetch
Fetch --> Cache
Cache --> Merge
Local --> Merge
Merge --> Combined
style Sources fill:#0d47a1,stroke:#2196f3,stroke-width:2px,color:#ffffff
style Fetch fill:#1b5e20,stroke:#4caf50,stroke-width:2px,color:#ffffff
style Cache fill:#37474f,stroke:#78909c,stroke-width:2px,color:#ffffff
style Merge fill:#e65100,stroke:#ff9800,stroke-width:3px,color:#ffffff
style Local fill:#4a148c,stroke:#9c27b0,stroke-width:2px,color:#ffffff
style Combined fill:#880e4f,stroke:#c2185b,stroke-width:2px,color:#ffffff
```
### Configuration
Dynamic profile sources are defined in `config.yaml` as an array:
```yaml
dynamic_profile_sources:
- url: "https://example.com/team-profiles.yaml"
headers:
Authorization: "Bearer <token>"
refresh_interval_secs: 1800
max_size_bytes: 1048576
fetch_timeout_secs: 10
enabled: true
conflict_resolution: "local_wins"
- url: "https://internal.corp/devops-profiles.yaml"
refresh_interval_secs: 3600
```
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `url` | string | (required) | URL to fetch profiles from |
| `headers` | map | `{}` | Custom HTTP headers (e.g., auth tokens) |
| `refresh_interval_secs` | integer | `1800` | How often to re-fetch the source (in seconds) |
| `max_size_bytes` | integer | `1048576` | Maximum response size (1 MB default) |
| `fetch_timeout_secs` | integer | `10` | HTTP fetch timeout in seconds |
| `enabled` | boolean | `true` | Whether this source is active |
| `conflict_resolution` | string | `"local_wins"` | How to handle ID collisions with local profiles |
There is no per-source option for allowing plain HTTP. Whether `http://` URLs are permitted comes from the single global `allow_http_profiles` setting (default `false`), which is applied to every source at load time; adding an `allow_http` key to a source entry in `config.yaml` does nothing.
### Background Refresh
Dynamic profile sources refresh automatically on a configurable timer:
- The default refresh interval is 1800 seconds (30 minutes)
- Each source can have its own interval via `refresh_interval_secs`
- Refresh occurs in the background without blocking the UI
- Failed fetches retain the previously cached version
### Local Cache
Fetched profiles are cached locally to provide offline access and faster startup:
**Cache location:** `~/.config/par-term/cache/dynamic_profiles/`
- Each source URL maps to a separate cache file
- The cache is populated on first fetch and updated on each successful refresh
- On startup, par-term loads from cache immediately and refreshes in the background
### Conflict Resolution
When a dynamic profile has the same ID as a local profile, the `conflict_resolution` setting determines which takes precedence:
| Mode | Description |
|------|-------------|
| `local_wins` | Local profile takes precedence (default) |
| `remote_wins` | Dynamic profile overrides the local one |
### Security
A dynamic profile source can influence what command a shell runs, so the fetch path is defended at several layers.
- **Scheme allowlist**: only `https` is accepted, plus `http` when the global `allow_http_profiles` is `true`. This is an allowlist, not a `file://` denylist — every other scheme (`ftp:`, `data:`, `file:`, anything else) is rejected outright, regardless of the HTTP opt-in. Scheme matching is case-insensitive, so `HTTPS://` is recognised as HTTPS rather than misclassified
- **No credentials in the clear**: even with the HTTP opt-in enabled, a source whose headers include `Authorization`, or any header name containing `token` or `secret`, is refused rather than fetched. The opt-in permits plaintext transport, never plaintext credentials
- **Redirects cannot downgrade**: an `https` source is fetched with HTTPS enforced across the whole redirect chain, so a `302` answering with an `http://` `Location` fails instead of quietly continuing in the clear. (A source you explicitly opted into HTTP for has no such protection, by definition — it is already plaintext)
- **HTTP is loud**: when a source is fetched over plain HTTP, a warning naming the URL is written to both the debug log and the standard log on every fetch
- **Size limits**: a response body larger than `max_size_bytes` (1 MB by default) fails the fetch rather than being truncated and parsed, and `fetch_timeout_secs` (10s by default) bounds the request as a whole. Either way the source keeps its previously cached profiles
- **Catch-all command profiles are rejected at merge**: a fetched profile that pairs a command with a catch-all auto-switch pattern (`*` or `**` in `hostname_patterns`, `directory_patterns` or `tmux_session_patterns`) is dropped and logged rather than added. Such a profile would fire its command on the first hostname or directory the terminal reports. You can still write one locally; a remote source cannot
- **Fetched commands are never pre-approved**: a command carried by a dynamic profile re-confirms on every auto-switch even after an "Always Allow" — see [Profile Commands and Confirmation](#profile-commands-and-confirmation)
### Visual Indicators
Dynamic profiles are visually distinguished throughout the interface:
- A `[dynamic]` badge appears next to dynamic profile names in the profile modal and profile drawer
- Dynamic profiles are read-only; opening one shows a "managed by a remote source" notice and all form fields are disabled
- Edit and delete controls are disabled for dynamic profiles in the profile list
### Keybinding
Use the `reload_dynamic_profiles` action to manually trigger an immediate refresh of all dynamic profile sources:
```yaml
keybindings:
- key: "CmdOrCtrl+Shift+F5"
action: "reload_dynamic_profiles"
```
### Dynamic Profiles Settings UI
Dynamic profile sources can be managed in **Settings > Profiles > Dynamic Sources**:
- Add, edit, and remove remote source URLs
- Configure per-source headers, refresh interval, and size limits
- Set conflict resolution mode
- Enable or disable individual sources without removing them
## Storage
Profiles are stored in YAML format:
**Location:** `~/.config/par-term/profiles.yaml`
**Format:**
```yaml
- id: 550e8400-e29b-41d4-a716-446655440000
name: Development
working_directory: ~/projects
icon: "\U0001F4BB"
order: 0
- id: 6fa459ea-ee8a-3ca4-894e-db77e160355e
name: SSH Server
command: ssh
command_args:
- user@server
icon: "\U0001F310"
order: 1
```
**Key Points:**
- UUIDs uniquely identify each profile
- Order field controls display sequence
- Changes save immediately when clicking **Save** in the modal
**How the file is written:** profiles carry commands and SSH arguments, so `profiles.yaml` is written atomically and owner-only. The new contents are staged in a temporary file in the same directory at mode `0600`, flushed to disk, and then renamed over the target — so the final file is mode `0600` on Unix regardless of your umask, and an interrupted or failed save leaves the previous `profiles.yaml` byte-for-byte intact rather than truncated. That matters because a truncated profiles file parses as "no profiles" rather than as an error.
## Related Documentation
- [Keyboard Shortcuts](../guides/KEYBOARD_SHORTCUTS.md) - Profile keyboard shortcuts
- [Tabs](TABS.md) - Tab management and directory inheritance
- [SSH Host Management](SSH.md) - SSH profiles and host-based auto-switching
- [Badges](BADGES.md) - Badge system and variables
- [Integrations](INTEGRATIONS.md) - Shell integration for directory tracking