feat: copilot-ssh reachability pre-flight, Windows Terminal profile and PATH tweaks - #610
Merged
Conversation
The cached status lines baked the rendered duration into the cache, so "ran 29s ago" stayed frozen until the next refresh. The collectors now store absolute epoch tokens (@ago:<epoch>@ / @in:<epoch>@) and the section commands expand them against the current clock on every run, using bash builtins only so the login hot path stays fork-free. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a reachability pre-flight to the bash, fish and PowerShell helpers, running before the 1Password unlock: - Resolve the destination with `ssh -G` (honours ~/.ssh/config aliases, HostName/Port overrides and -o flags). - Probe its TCP port with a hard ~3s timeout (nc, bash /dev/tcp or a .NET TcpClient), so an unreachable host fails fast instead of hanging. - When the probe fails and the Azure CLI is installed, look the host up with `az vm list -d`: by VM name, by the short form of an FQDN (vm01.example.com also matches vm01) and by public/private IP. - Offer to `az vm start` a stopped or deallocated VM, wait for the SSH port, then connect. Running-but-unreachable and ambiguous matches abort with actionable guidance. Tunable via COPILOT_SSH_SKIP_PREFLIGHT, COPILOT_SSH_PREFLIGHT_TIMEOUT, COPILOT_SSH_START_TIMEOUT and COPILOT_SSH_ASSUME_YES. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Set-WindowsTerminalCopilotProfile surgically patches settings.json with a profile that opens PowerShell and runs copilot-ssh against the configured host. The profile uses a fixed GUID so re-runs update the same entry instead of duplicating it, and unrelated settings are preserved. The host comes from the new `copilotSshHost` chezmoi variable, which defaults to the svlazdev.<privateDomain> alias already declared in the managed ssh config (falling back to plain svlazdev when privateDomain is empty) and can be overridden per machine. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Persist %OneDrive%\Portable Programs in the user-scope PATH so it survives reboots and is visible to GUI apps, and add it to the current PowerShell session from the profile. The persistent write goes through the registry directly, preserving the existing value name casing and RegistryValueKind, so REG_EXPAND_SZ entries such as %USERPROFILE%\bin keep expanding instead of being baked in by [Environment]::SetEnvironmentVariable. WM_SETTINGCHANGE is broadcast afterwards so running apps pick the change up. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The test set PATH to "$TEST_DIR:/usr/bin:/bin" to simulate a host without the Azure CLI, but GitHub Actions runners ship az in /usr/bin, so the real CLI was invoked and the expected 'install the Azure CLI' hint never appeared. Build a minimal PATH containing only the stubs plus the tools the helper needs, so the command is genuinely absent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR improves day-to-day shell and Windows ergonomics in this dotfiles repo by (1) fixing fastfetch status relative-time caching so it doesn’t “freeze”, (2) adding a reachability pre-flight to copilot-ssh across bash/fish/PowerShell (with optional Azure VM start assistance), and (3) adding Windows automation for a Windows Terminal “Copilot SSH” profile plus a persistent/user-scope OneDrive “Portable Programs” PATH entry.
Changes:
- Fastfetch status cache now stores absolute epoch tokens and renders relative times at emit-time.
copilot-sshgains a TCP reachability pre-flight and Azure VM recovery flow across shells, with new unit tests.- Windows setup adds an idempotent Windows Terminal profile patcher and a PATH persistence helper (with Pester coverage), plus docs/chezmoi-variable wiring.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/powershell/WindowsTerminal.Tests.ps1 | Updates fixtures handling and adds unit tests for the new Windows Terminal Copilot profile helper. |
| tests/powershell/Profile.Tests.ps1 | Registers new Copilot SSH helper functions as private helpers for module export hygiene tests. |
| tests/powershell/PortableProgramsPath.Tests.ps1 | New Pester coverage for OneDrive “Portable Programs” PATH persistence + profile session behavior. |
| tests/powershell/CopilotSsh.Tests.ps1 | Adds unit tests validating reachability pre-flight behavior and helper privacy. |
| tests/bash/fastfetch-status.bats | Extends Bats coverage for epoch-token caching and dynamic relative-time rendering. |
| tests/bash/copilot-ssh.bats | Adds Bats coverage for reachability probe + Azure-assisted recovery flow. |
| home/dot_config/shell/functions/copilot-ssh.sh | Implements bash/zsh pre-flight probe + Azure VM recovery helpers. |
| home/dot_config/fish/functions/copilot_ssh.fish | Implements fish pre-flight probe + Azure VM recovery helpers. |
| home/dot_config/powershell/modules/DotfilesHelpers/Public/CopilotSsh.ps1 | Implements PowerShell pre-flight probe helpers and integrates into Connect-CopilotSsh. |
| home/dot_config/powershell/modules/DotfilesHelpers/Public/WindowsTerminal.ps1 | Adds Set-WindowsTerminalCopilotProfile to surgically patch Windows Terminal settings.json. |
| home/dot_config/powershell/modules/DotfilesHelpers/DotfilesHelpers.psd1 | Exports the new Windows Terminal Copilot profile function. |
| home/dot_config/powershell/profile.ps1 | Adds cheap per-session PATH augmentation for OneDrive “Portable Programs”. |
| home/dot_config/fastfetch/executable_status.sh | Switches to epoch-token caching and on-demand relative-time rendering for fastfetch status. |
| home/.chezmoiscripts/windows/run_onchange_set-windows-terminal-copilot-profile.ps1.tmpl | New run-onchange script to keep Windows Terminal Copilot SSH profile configured. |
| home/.chezmoiscripts/windows/run_onchange_add-portable-programs-path.ps1 | New run-onchange script to persist OneDrive “Portable Programs” in user PATH via registry. |
| home/.chezmoi.yaml.tmpl | Introduces copilotSshHost variable wiring into chezmoi data. |
| docs/customization.md | Documents the Windows PATH behavior. |
| docs/copilot-cli.md | Documents the new reachability pre-flight and Azure VM behavior. |
| docs/chezmoi-variables.md | Documents the new copilotSshHost chezmoi variable. |
Comments suppressed due to low confidence (1)
home/dot_config/fastfetch/executable_status.sh:87
- _now() still forks
dateon bash versions without EPOCHSECONDS, despite the goal of keeping the emit path cheap. Bash’s builtin printf time format can provide epoch seconds without spawning a process on many older bash versions too.
# _now -> current epoch seconds (bash 5 builtin when available).
_now() {
if [ -n "${EPOCHSECONDS:-}" ]; then
printf '%s\n' "${EPOCHSECONDS}"
else
date +%s
fi
}
Comment on lines
+28
to
+29
| $script:ArtifactsRoot = Join-Path $script:RepoRoot ".test-artifacts" | ||
| $script:TestDir = New-Item -ItemType Directory -Path (Join-Path $script:ArtifactsRoot "wt-settings-tests-$(Get-Random)") -Force |
Comment on lines
+118
to
+126
| printf 'copilot-ssh: waiting for %s:%s to accept connections' "${host}" "${port}" >&2 | ||
| while [ "${waited}" -lt "${limit}" ]; do | ||
| if _copilot_ssh_tcp_probe "${host}" "${port}" 3; then | ||
| printf ' up\n' >&2 | ||
| return 0 | ||
| fi | ||
| printf '.' >&2 | ||
| sleep 5 | ||
| waited=$((waited + 5)) |
Comment on lines
+185
to
+189
| while test $waited -lt $limit | ||
| if _copilot_ssh_tcp_probe $host $port 3 | ||
| printf ' up\n' >&2 | ||
| return 0 | ||
| end |
Comment on lines
+19
to
+23
| # Relative times ("ran 5m ago", "next in 20m") are NOT baked into the cache | ||
| # — that would freeze them until the next refresh. The collectors store | ||
| # absolute epoch tokens (@ago:<epoch>@ / @in:<epoch>@) and the section | ||
| # commands expand them against the current clock on every fastfetch run, | ||
| # using bash builtins only (no forks). |
Comment on lines
+139
to
+144
| | Variable | Default | Effect | | ||
| | ------------------------------- | ------- | ----------------------------------------------- | | ||
| | `COPILOT_SSH_SKIP_PREFLIGHT` | unset | `1` skips the reachability check entirely | | ||
| | `COPILOT_SSH_PREFLIGHT_TIMEOUT` | `3` | TCP probe timeout in seconds | | ||
| | `COPILOT_SSH_START_TIMEOUT` | `180` | How long to wait for SSH after `az vm start` | | ||
| | `COPILOT_SSH_ASSUME_YES` | unset | `1` auto-confirms starting a stopped VM | |
Comment on lines
+462
to
+463
| else { | ||
| if ($null -eq $copilotProfile.PSObject.Properties['hidden']) { |
- Don't spin the post-`az vm start` wait loop for the full timeout when no TCP probe tool is available: an undetermined probe now stops waiting and lets ssh report the real state (bash and fish). - Collapse duplicate Windows Terminal profiles sharing the fixed Copilot GUID, so manual edits can't leave conflicting entries behind. - Honour COPILOT_SSH_ASSUME_NO in the bash and fish helpers for parity with PowerShell, and document it alongside the other pre-flight variables. - Correct the fastfetch status header: relative-time expansion is pure shell arithmetic, but reading the clock costs one `date` fork on bash < 5.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
DevSecNinja
enabled auto-merge (squash)
July 28, 2026 07:47
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four related quality-of-life changes to the shell/Windows setup.
fix(fastfetch): relative times no longer freezeThe status cache baked the rendered duration into the cache file, so
ran 29s agostayed static until the next refresh. Collectors now storeabsolute epoch tokens (
@ago:<epoch>@/@in:<epoch>@) and the sectioncommands expand them against the current clock on every fastfetch run,
using bash builtins only so the login hot path stays fork-free. An elapsed
timer renders
next due.feat(helpers): copilot-ssh reachability pre-flightRuns in bash, fish and PowerShell before the 1Password unlock:
ssh -G(honours~/.ssh/configaliases,HostName/Portoverrides and-oflags).nc, bash/dev/tcp, or a.NET
TcpClient), so an unreachable host fails fast instead of hanging.az vm list -d— by VM name, by the short form of an FQDN(
vm01.example.comalso matchesvm01), and by public/private IP.az vm starta stopped/deallocated VM, wait for the port, thenconnect. Running-but-unreachable and ambiguous matches abort with
actionable guidance.
Tunable with
COPILOT_SSH_SKIP_PREFLIGHT,COPILOT_SSH_PREFLIGHT_TIMEOUT,COPILOT_SSH_START_TIMEOUTandCOPILOT_SSH_ASSUME_YES.feat(windows): Windows Terminal profile for copilot-sshSet-WindowsTerminalCopilotProfilesurgically patchessettings.jsonwith afixed-GUID profile that opens PowerShell and runs
copilot-ssh <host>.Idempotent, preserves unrelated settings. The host comes from the new
copilotSshHostchezmoi variable, defaulting to thesvlazdev.<privateDomain>alias already declared in the managed ssh config.feat(windows): OneDrive Portable Programs on PATHPersists
%OneDrive%\Portable Programsin the user-scope PATH (survivesreboots, visible to GUI apps) and adds it to the current PowerShell session.
The persistent write goes through the registry directly, preserving the
existing value name casing and
RegistryValueKind, soREG_EXPAND_SZentries like
%USERPROFILE%\binkeep expanding instead of being baked in by[Environment]::SetEnvironmentVariable. BroadcastsWM_SETTINGCHANGE.Testing
./tests/bash/run-tests.sh --ci— green except two pre-existinglog-structured.batsJSON failures (backslash double-escaping inlog.sh, untouched by this PR).Invoke-Pester ./tests/powershell— 439 passed, 0 failed.shellcheck -x/shfmt --diff/fish -nclean on all changed files.Notes
After applying, run
~/.config/fastfetch/status.sh refresh --forceonce toreplace the old frozen cache line.