Skip to content

feat: copilot-ssh reachability pre-flight, Windows Terminal profile and PATH tweaks - #610

Merged
DevSecNinja merged 6 commits into
mainfrom
feat/copilot-ssh-preflight
Jul 28, 2026
Merged

feat: copilot-ssh reachability pre-flight, Windows Terminal profile and PATH tweaks#610
DevSecNinja merged 6 commits into
mainfrom
feat/copilot-ssh-preflight

Conversation

@DevSecNinja

Copy link
Copy Markdown
Owner

Summary

Four related quality-of-life changes to the shell/Windows setup.

fix(fastfetch): relative times no longer freeze

The status cache baked the rendered duration into the cache file, so
ran 29s ago stayed static until the next refresh. Collectors now 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 so the login hot path stays fork-free. An elapsed
timer renders next due.

feat(helpers): copilot-ssh reachability pre-flight

Runs in bash, fish and PowerShell before the 1Password unlock:

  1. Resolve the destination with ssh -G (honours ~/.ssh/config aliases,
    HostName/Port overrides and -o flags).
  2. Probe the TCP port with a hard ~3s timeout (nc, bash /dev/tcp, or a
    .NET TcpClient), so an unreachable host fails fast instead of hanging.
  3. If the probe fails and the Azure CLI is present, 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.
  4. Offer to az vm start a stopped/deallocated VM, wait for the port, then
    connect. Running-but-unreachable and ambiguous matches abort with
    actionable guidance.

Tunable with COPILOT_SSH_SKIP_PREFLIGHT, COPILOT_SSH_PREFLIGHT_TIMEOUT,
COPILOT_SSH_START_TIMEOUT and COPILOT_SSH_ASSUME_YES.

feat(windows): Windows Terminal profile for copilot-ssh

Set-WindowsTerminalCopilotProfile surgically patches settings.json with a
fixed-GUID profile that opens PowerShell and runs copilot-ssh <host>.
Idempotent, preserves unrelated settings. The host comes from the new
copilotSshHost chezmoi variable, defaulting to the
svlazdev.<privateDomain> alias already declared in the managed ssh config.

feat(windows): OneDrive Portable Programs on PATH

Persists %OneDrive%\Portable Programs in the user-scope PATH (survives
reboots, 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, so REG_EXPAND_SZ
entries like %USERPROFILE%\bin keep expanding instead of being baked in by
[Environment]::SetEnvironmentVariable. Broadcasts WM_SETTINGCHANGE.

Testing

  • ./tests/bash/run-tests.sh --ci — green except two pre-existing
    log-structured.bats JSON failures (backslash double-escaping in
    log.sh, untouched by this PR).
  • Invoke-Pester ./tests/powershell — 439 passed, 0 failed.
  • shellcheck -x / shfmt --diff / fish -n clean on all changed files.

Notes

After applying, run ~/.config/fastfetch/status.sh refresh --force once to
replace the old frozen cache line.

DevSecNinja and others added 4 commits July 28, 2026 08:57
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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-ssh gains 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 date on 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 thread docs/copilot-cli.md
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
DevSecNinja enabled auto-merge (squash) July 28, 2026 07:47
@DevSecNinja
DevSecNinja merged commit aa90b05 into main Jul 28, 2026
19 checks passed
@DevSecNinja
DevSecNinja deleted the feat/copilot-ssh-preflight branch July 28, 2026 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants