From aa291cc5458cf8d1ca49af294ae6e4b068f92202 Mon Sep 17 00:00:00 2001 From: tevans Date: Thu, 18 Jun 2026 20:51:18 +0100 Subject: [PATCH] Initial Warp dotfiles: configs + symlink installer Co-Authored-By: Oz --- .gitignore | 8 ++ README.md | 81 +++++++++++++ install.ps1 | 132 ++++++++++++++++++++++ warp/config/settings.toml | 111 ++++++++++++++++++ warp/data/tab_configs/startup_config.toml | 8 ++ warp/data/themes/.gitkeep | 0 6 files changed, 340 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 install.ps1 create mode 100644 warp/config/settings.toml create mode 100644 warp/data/tab_configs/startup_config.toml create mode 100644 warp/data/themes/.gitkeep diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..783c108 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +# Backups created by install.ps1 +*.bak-* +*.bak + +# OS / editor cruft +Thumbs.db +Desktop.ini +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..4529b3d --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# warp-dotfiles + +Version-controlled [Warp](https://www.warp.dev/) configuration, symlinked into +place on each machine so file-based settings follow me everywhere. + +This complements — it does not replace — Warp's cloud features: + +- **Settings Sync** (cloud) handles themes, AI settings, feature toggles, and + privacy settings automatically on login. +- **Warp Drive Workflows** (cloud) store reusable, parameterized commands + (e.g. SSH connections). +- **This repo** captures the file-based bits Settings Sync skips: custom + keybindings, custom themes, YAML/tab configs, and local `settings.toml`. + +## Layout + +``` +warp-dotfiles/ +├── install.ps1 # symlink installer (Windows / PowerShell) +├── README.md +└── warp/ + ├── data/ # -> %APPDATA%\warp\Warp\data + │ ├── keybindings.yaml # custom keybindings (if present) + │ ├── tab_configs/ # launch / tab configs (TOML) + │ └── themes/ # custom themes + └── config/ # -> %LOCALAPPDATA%\warp\Warp\config + └── settings.toml # device settings +``` + +## Symlink mapping + +| Repo path | Target on Windows | +| ------------------------------- | ----------------------------------------------- | +| `warp\data\tab_configs` | `%APPDATA%\warp\Warp\data\tab_configs` | +| `warp\data\themes` | `%APPDATA%\warp\Warp\data\themes` | +| `warp\data\keybindings.yaml` | `%APPDATA%\warp\Warp\data\keybindings.yaml` | +| `warp\config\settings.toml` | `%LOCALAPPDATA%\warp\Warp\config\settings.toml` | + +Entries whose source does not exist in the repo are skipped, so the script is +safe to run even before you've added keybindings or themes. + +> Note: `settings.toml` includes some device-specific values (e.g. startup +> shell). If you don't want it shared across machines, remove that entry from +> `$Entries` in `install.ps1`. + +## Set up on a new machine + +1. Enable **Developer Mode** so non-admin symlink creation works: + Settings > Privacy & security > For developers > Developer Mode. + (Alternatively, run the installer from an elevated PowerShell.) +2. Clone and run: + + ```powershell + git clone https://github.com//warp-dotfiles.git $env:USERPROFILE\warp-dotfiles + cd $env:USERPROFILE\warp-dotfiles + pwsh -ExecutionPolicy Bypass -File .\install.ps1 + ``` + +3. Restart Warp. + +### Useful flags + +```powershell +pwsh -File .\install.ps1 -DryRun # preview changes, write nothing +pwsh -File .\install.ps1 -Force # delete existing real targets instead of backing them up +``` + +Existing real files at a target are backed up to `.bak-` +unless `-Force` is used. + +## Updating + +Because the targets are symlinks back into this repo, edits made in Warp land +directly in the working tree. Commit and push as usual: + +```powershell +cd $env:USERPROFILE\warp-dotfiles +git add -A +git commit -m "Update Warp config" +git push +``` diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..398f1e1 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,132 @@ +<# +.SYNOPSIS + Symlinks Warp configuration files from this dotfiles repo into the + locations Warp reads on Windows. + +.DESCRIPTION + For each managed entry, the script: + * Ensures the target's parent directory exists. + * If a real file/dir already lives at the target, backs it up to + ".bak-" (unless -Force is used, which deletes it). + * Replaces an existing symlink at the target. + * Creates a new symlink target -> repo source. + + Creating symlinks on Windows requires either: + * Developer Mode enabled (Settings > Privacy & security > For developers), or + * Running this script from an elevated (Administrator) PowerShell. + +.PARAMETER DryRun + Print what would happen without making changes. + +.PARAMETER Force + Delete existing real targets instead of backing them up. + +.EXAMPLE + pwsh -ExecutionPolicy Bypass -File .\install.ps1 + pwsh -File .\install.ps1 -DryRun +#> +[CmdletBinding()] +param( + [switch]$DryRun, + [switch]$Force +) + +$ErrorActionPreference = 'Stop' +$RepoRoot = $PSScriptRoot + +# Resolve Warp config roots. APPDATA = Roaming (data), LOCALAPPDATA = Local (config). +$DataRoot = Join-Path $env:APPDATA 'warp\Warp\data' +$ConfigRoot = Join-Path $env:LOCALAPPDATA 'warp\Warp\config' + +# Managed entries: Source is relative to the repo, Target is absolute. +# Type is 'File' or 'Directory' (controls how the symlink is created). +$Entries = @( + @{ Source = 'warp\data\tab_configs'; Target = (Join-Path $DataRoot 'tab_configs'); Type = 'Directory' } + @{ Source = 'warp\data\themes'; Target = (Join-Path $DataRoot 'themes'); Type = 'Directory' } + @{ Source = 'warp\data\keybindings.yaml'; Target = (Join-Path $DataRoot 'keybindings.yaml'); Type = 'File' } + @{ Source = 'warp\config\settings.toml'; Target = (Join-Path $ConfigRoot 'settings.toml'); Type = 'File' } +) + +function Test-SymlinkCapability { + # Admin always works. + $id = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = New-Object Security.Principal.WindowsPrincipal($id) + if ($principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + return $true + } + # Otherwise check Developer Mode. + $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock' + try { + $val = (Get-ItemProperty -Path $key -Name AllowDevelopmentWithoutDevLicense -ErrorAction Stop).AllowDevelopmentWithoutDevLicense + return ($val -eq 1) + } catch { + return $false + } +} + +function Backup-Target { + param([string]$Path) + $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' + $backup = "$Path.bak-$stamp" + Write-Host " backing up existing target -> $backup" -ForegroundColor Yellow + if (-not $DryRun) { Move-Item -LiteralPath $Path -Destination $backup -Force } +} + +Write-Host "Warp dotfiles installer" -ForegroundColor Cyan +Write-Host " repo: $RepoRoot" +Write-Host " data root: $DataRoot" +Write-Host " config root: $ConfigRoot" +if ($DryRun) { Write-Host " MODE: DryRun (no changes)" -ForegroundColor Magenta } +Write-Host "" + +if (-not (Test-SymlinkCapability)) { + Write-Warning @" +Symlink creation may fail. Enable Developer Mode +(Settings > Privacy & security > For developers > Developer Mode) +or re-run this script from an elevated (Administrator) PowerShell. +"@ +} + +foreach ($entry in $Entries) { + $source = Join-Path $RepoRoot $entry.Source + $target = $entry.Target + + Write-Host ("-> {0}" -f $entry.Source) -ForegroundColor Cyan + + if (-not (Test-Path -LiteralPath $source)) { + Write-Host " skip: source does not exist in repo ($source)" -ForegroundColor DarkGray + continue + } + + # Ensure parent dir of target exists. + $parent = Split-Path -Parent $target + if (-not (Test-Path -LiteralPath $parent)) { + Write-Host " creating parent dir: $parent" + if (-not $DryRun) { New-Item -ItemType Directory -Force -Path $parent | Out-Null } + } + + # Handle anything already at the target. + if (Test-Path -LiteralPath $target) { + $item = Get-Item -LiteralPath $target -Force + $isLink = $item.LinkType -eq 'SymbolicLink' -or [bool]($item.Attributes -band [IO.FileAttributes]::ReparsePoint) + if ($isLink) { + Write-Host " removing existing symlink" + if (-not $DryRun) { (Get-Item -LiteralPath $target -Force).Delete() } + } + elseif ($Force) { + Write-Host " removing existing target (-Force)" -ForegroundColor Yellow + if (-not $DryRun) { Remove-Item -LiteralPath $target -Recurse -Force } + } + else { + Backup-Target -Path $target + } + } + + Write-Host " linking $target -> $source" -ForegroundColor Green + if (-not $DryRun) { + New-Item -ItemType SymbolicLink -Path $target -Target $source | Out-Null + } +} + +Write-Host "" +Write-Host "Done." -ForegroundColor Cyan diff --git a/warp/config/settings.toml b/warp/config/settings.toml new file mode 100644 index 0000000..bd0389a --- /dev/null +++ b/warp/config/settings.toml @@ -0,0 +1,111 @@ +[privacy] +telemetry_enabled = true +crash_reporting_enabled = true +custom_secret_regex_list = [ + { name = "IPv4 Address", pattern = '\b((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}\b' }, + { + name = "IPv6 Address", + pattern = '\b((([0-9A-Fa-f]{1,4}:){1,6}:)|(([0-9A-Fa-f]{1,4}:){7}))([0-9A-Fa-f]{1,4})\b', + }, + { name = "Slack App Token", pattern = '\bxapp-[0-9]+-[A-Za-z0-9_]+-[0-9]+-[a-f0-9]+\b' }, + { name = "Phone Number", pattern = '\b(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}\b' }, + { + name = "AWS Access ID", + pattern = '\b(AKIA|A3T|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{12,}\b', + }, + { + name = "MAC Address", + pattern = '\b((([a-zA-z0-9]{2}[-:]){5}([a-zA-z0-9]{2}))|(([a-zA-z0-9]{2}:){5}([a-zA-z0-9]{2})))\b', + }, + { name = "Google API Key", pattern = '\bAIza[0-9A-Za-z-_]{35}\b' }, + { name = "Google OAuth ID", pattern = '\b[0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com\b' }, + { name = "GitHub Classic Personal Access Token", pattern = '\bghp_[A-Za-z0-9_]{36}\b' }, + { name = "GitHub Fine-Grained Personal Access Token", pattern = '\bgithub_pat_[A-Za-z0-9_]{82}\b' }, + { name = "GitHub OAuth Access Token", pattern = '\bgho_[A-Za-z0-9_]{36}\b' }, + { name = "GitHub User-to-Server Token", pattern = '\bghu_[A-Za-z0-9_]{36}\b' }, + { name = "GitHub Server-to-Server Token", pattern = '\bghs_[A-Za-z0-9_]{36}\b' }, + { name = "Stripe Key", pattern = '\b(?:r|s)k_(test|live)_[0-9a-zA-Z]{24}\b' }, + { name = "Firebase Auth Domain", pattern = '\b([a-z0-9-]){1,30}(\.firebaseapp\.com)\b' }, + { name = "JWT", pattern = '\b(ey[a-zA-z0-9_\-=]{10,}\.){2}[a-zA-z0-9_\-=]{10,}\b' }, + { name = "OpenAI API Key", pattern = '\bsk-[a-zA-Z0-9]{48}\b' }, + { name = "Anthropic API Key", pattern = '\bsk-ant-api\d{0,2}-[a-zA-Z0-9\-]{80,120}\b' }, + { name = "Generic SK API Key", pattern = '\bsk-[a-zA-Z0-9\-]{10,100}\b' }, + { name = "Fireworks API Key", pattern = '\bfw_[a-zA-Z0-9]{24}\b' }, +] + +[general] +default_session_mode = "agent" + +[agents] +cloud_conversation_storage_enabled = true + +[agents.mcp_servers] +file_based_mcp_enabled = true + +[agents.warp_agent] +is_any_ai_enabled = true + +[agents.warp_agent.input] +nld_in_terminal_enabled = true +ai_auto_detection_enabled = false + +[agents.warp_agent.other] +cloud_agent_computer_use_enabled = true +show_conversation_history = true +show_agent_notifications = true + +[agents.profiles] +agent_mode_execute_readonly_commands = true + +[agents.third_party] +should_render_cli_agent_toolbar = true + +[appearance] + +[appearance.themes] +system_theme = true +theme = "cyber_wave" +selected_system_themes = { dark = "dark", light = "solarized_dark" } + +[appearance.panes] +should_dim_inactive_panes = true + +[appearance.input] +input_mode = "waterfall" + +[appearance.vertical_tabs] +enabled = true + +[notifications] + +[notifications.preferences] +is_agent_task_completed_enabled = true +is_long_running_enabled = true +is_needs_attention_enabled = true +is_password_prompt_enabled = true +long_running_threshold = 30 +mode = "enabled" +play_notification_sound = true + +[code] + +[code.indexing] +agent_mode_codebase_context_auto_indexing = true + +[code.editor] +show_code_review_button = true +show_global_search = true +show_project_explorer = true + +[terminal] +use_audible_bell = true +osc52_clipboard_access = "write_only" + +[terminal.input] +input_box_type_setting = "universal" + +[account] +is_settings_sync_enabled = true + +[warp_drive] +enabled = true diff --git a/warp/data/tab_configs/startup_config.toml b/warp/data/tab_configs/startup_config.toml new file mode 100644 index 0000000..92f7189 --- /dev/null +++ b/warp/data/tab_configs/startup_config.toml @@ -0,0 +1,8 @@ +name = "New tab: tevans" + +[[panes]] +id = "main" +type = "terminal" +directory = 'C:\Users\tevans' + +[params] diff --git a/warp/data/themes/.gitkeep b/warp/data/themes/.gitkeep new file mode 100644 index 0000000..e69de29