diff --git a/PLAN.md b/PLAN.md index 4cb3056..901e4a5 100644 --- a/PLAN.md +++ b/PLAN.md @@ -66,13 +66,14 @@ is still open. For the full requirements, see [SPEC.md](SPEC.md). - [ ] Paginate/scroll the secrets diff table for secrets with many fields instead of relying on terminal wrapping. -## Phase 3 — Windows-native support (open, secondary priority) +## Phase 3 — Windows-native support (done) -- [ ] Detect OS at runtime; on native Windows (no WSL), fall back to - `wt.exe split-pane` instead of `tmux` for the status panes. -- [ ] Document/implement that `Esc`-triggered session close is **not** - available in the native Windows fallback — the panes must be closed - manually there. +- [x] Windows support via [psmux](https://github.com/marlocarlo/psmux) — + a native, tmux-compatible terminal multiplexer. kctl-tui works + without code changes; `CheckTool("tmux")` error message includes + Windows-specific install hint. +- [x] `install.ps1` — PowerShell install script for Windows. +- [x] Updated README and SPEC with Windows + psmux setup instructions. ## Phase 4 — Nice-to-haves (open, not committed) diff --git a/README.md b/README.md index 2f41422..a87aa76 100644 --- a/README.md +++ b/README.md @@ -68,12 +68,16 @@ See [SPEC.md](SPEC.md) for the full requirements and design rationale, and Configuration below - they must already exist in your kubeconfig, e.g. added via `aws eks update-kubeconfig`). - `k9s` (used for the two status panes). -- `tmux` (used for the 3-pane layout). On Windows, this means running - kctl-tui inside **WSL** — `tmux` has no native Windows port. Native - Windows Terminal has its own split-pane feature, but it cannot be - scripted from inside a pane the way `tmux` can, so the automated 3-pane - layout and the `Esc` session handling described above are only fully - supported under Linux/WSL. See SPEC.md section 3.6 for details. +- `tmux` (used for the 3-pane layout). On **Linux/macOS**, install + `tmux` via your package manager. On **Windows**, install + [psmux](https://github.com/marlocarlo/psmux) — a native, + tmux-compatible terminal multiplexer: + ```powershell + scoop install psmux + # or + cargo install psmux + ``` + psmux provides a `tmux` command, so kctl-tui works without changes. - `aws` CLI, configured with credentials, only needed for the secrets workflow. @@ -85,6 +89,15 @@ See [SPEC.md](SPEC.md) for the full requirements and design rationale, and curl -fsSL https://raw.githubusercontent.com/skoelle/kctl-tui/main/install.sh | bash ``` +### Quick install (Windows) + +```powershell +irm https://raw.githubusercontent.com/skoelle/kctl-tui/main/install.ps1 | iex +``` + +This downloads the latest release binary for your architecture from +GitHub Releases and installs it to your PATH. + This downloads the latest release binary for your OS/architecture from GitHub Releases and installs it to `/usr/local/bin/kctl-tui`. @@ -167,11 +180,19 @@ aws_sso_login_command: "aws sso login" that way — it typically contains your organization's internal account ID, context naming, and label names. -## WSL setup notes +## Windows notes -If `kubectx`/`kubens` or `kctl-tui` report a missing kubeconfig inside WSL, -your kubeconfig most likely only exists on the Windows side. Symlink it -into WSL: +On native Windows (without WSL), install [psmux](https://github.com/marlocarlo/psmux) +for the 3-pane layout. psmux is a native Windows terminal multiplexer +that is tmux-compatible — kctl-tui works without code changes: + +```powershell +scoop install psmux +# or +cargo install psmux +``` + +If you prefer WSL, symlink your kubeconfig into WSL: ```bash mkdir -p ~/.kube diff --git a/SPEC.md b/SPEC.md index e52282e..9336c95 100644 --- a/SPEC.md +++ b/SPEC.md @@ -167,18 +167,15 @@ The `context_template` replaces `{region}`, `{account_id}`, `{env}`, and selected environment/context. The resolved value must match an existing context in your kubeconfig (e.g. added via `aws eks update-kubeconfig`). -**Platform limitation on Windows without WSL:** `kill-session` is -tmux-specific. Windows Terminal (`wt.exe`) offers no equivalent scripting -to end the session from inside a pane. On plain Windows (without WSL), -only a simplified flow is possible: k9s panes are closed manually (`q`, -then `Ctrl+Shift+W`); automatic session termination is unavailable there. -This limitation is the main reason the primary target system is set to -Linux/WSL. +**Windows support:** On native Windows, install +[psmux](https://github.com/marlocarlo/psmux) — a native, tmux-compatible +terminal multiplexer. psmux provides a `tmux` command, so kctl-tui works +without code changes (including `Esc`-triggered session termination). +Alternatively, run kctl-tui inside WSL with standard `tmux`. ## 4. Non-functional requirements -- **Primary platform Linux/WSL**, secondary native Windows with reduced - functionality. +- **Primary platform Linux/WSL**, secondary native Windows (via psmux). - **Single-binary distribution** without external runtime dependency (Go provides this natively). - **External dependencies**: `kubectl` mandatory; `tmux`, `k9s`, `aws-cli` diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..a103e08 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,74 @@ +# Install script for kctl-tui on Windows. +# Downloads the latest GitHub release binary matching the current architecture +# and installs it to your PATH. +# +# Usage (PowerShell): +# irm https://raw.githubusercontent.com/skoelle/kctl-tui/main/install.ps1 | iex +# +# Or save and run locally: +# .\install.ps1 +# +# Requires: PowerShell 5.1+, internet access. + +$ErrorActionPreference = "Stop" + +$Repo = "skoelle/kctl-tui" +$BinName = "kctl-tui" + +# --- Detect architecture --- +$arch = $env:PROCESSOR_ARCHITECTURE +switch ($arch) { + "AMD64" { $goarch = "amd64" } + "ARM64" { $goarch = "arm64" } + default { + Write-Error "Unsupported architecture: $arch" + exit 1 + } +} + +# --- Determine install directory --- +$installDir = "$env:USERPROFILE\bin" +if (-not (Test-Path $installDir)) { + New-Item -ItemType Directory -Path $installDir | Out-Null +} + +# Add to PATH if not already there +$currentPath = [Environment]::GetEnvironmentVariable("Path", "User") +if ($currentPath -notlike "*$installDir*") { + [Environment]::SetEnvironmentVariable("Path", "$currentPath;$installDir", "User") + $env:Path = "$env:Path;$installDir" + Write-Host "Added $installDir to your PATH." +} + +# --- Query GitHub API for latest release --- +Write-Host "Detecting latest release for $Repo ..." +try { + $release = Invoke-RestMethod -Uri "https://api.github.com/repos/$Repo/releases/latest" -UseBasicParsing +} catch { + Write-Error "Failed to reach the GitHub API (network error). Check your internet connection and try again." + exit 1 +} + +$tag = $release.tag_name +if (-not $tag) { + Write-Error "Could not find a published release for $Repo. No release has been tagged yet." + exit 1 +} + +Write-Host "Latest release: $tag" + +# --- Download binary --- +$asset = "kctl-tui-windows-${goarch}.exe" +$url = "https://github.com/$Repo/releases/download/$tag/$asset" +$outFile = "$installDir\$BinName.exe" + +Write-Host "Downloading $asset ($tag) ..." +try { + Invoke-WebRequest -Uri $url -OutFile $outFile -UseBasicParsing +} catch { + Write-Error "Download failed: $_" + exit 1 +} + +Write-Host "Installed $BinName to $outFile" +Write-Host "Done. Run '$BinName' to get started." diff --git a/internal/kubeexec/kubeexec.go b/internal/kubeexec/kubeexec.go index d72667c..0c3081b 100644 --- a/internal/kubeexec/kubeexec.go +++ b/internal/kubeexec/kubeexec.go @@ -182,8 +182,11 @@ func RunAWSLogin(loginCommand string) *exec.Cmd { // Returns nil if found, or a descriptive error if not. func CheckTool(name string) error { _, err := exec.LookPath(name) - if err != nil { - return fmt.Errorf("%q not found in PATH — please install it first", name) + if err == nil { + return nil } - return nil + if name == "tmux" { + return fmt.Errorf("%q not found in PATH — install tmux (Linux/macOS) or psmux (Windows: scoop install psmux or cargo install psmux)", name) + } + return fmt.Errorf("%q not found in PATH — please install it first", name) }