aboutsummaryrefslogtreecommitdiff
path: root/website
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-08-18 22:39:38 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-08-18 22:39:38 +0300
commit9fac51722653fa0b0b6a5786166fb18c763424e0 (patch)
treea8efd3b30cf29a8fb11138b7444bb9baa0dac2fa /website
parent0bd445020ea19e0cea13f42a28212db7b2df196d (diff)
feat: make Windows generally available
Diffstat (limited to 'website')
-rw-r--r--website/agent-guide.md4
-rw-r--r--website/astro.config.mjs2
-rw-r--r--website/index.html6
-rw-r--r--website/install.ps1100
4 files changed, 82 insertions, 30 deletions
diff --git a/website/agent-guide.md b/website/agent-guide.md
index 7e20c751..71392817 100644
--- a/website/agent-guide.md
+++ b/website/agent-guide.md
@@ -32,14 +32,14 @@ curl -fsSL https://herdr.dev/install.sh | sh
herdr
```
-Windows preview beta:
+Windows:
```powershell
powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"
herdr
```
-Homebrew, mise, and Nix installs, verification, and manual downloads: https://herdr.dev/docs/install/. Direct installs update with `herdr update`; package-manager installs update through that package manager. Check the version with `herdr --version`.
+Homebrew, mise, and Nix installs, verification, and manual downloads: https://herdr.dev/docs/install/. Direct installs use the stable channel by default and update with `herdr update`; preview is opt-in. Package-manager installs update through that package manager. Check the version with `herdr --version`.
## First-run walkthrough
diff --git a/website/astro.config.mjs b/website/astro.config.mjs
index 84992ed2..8afbf46f 100644
--- a/website/astro.config.mjs
+++ b/website/astro.config.mjs
@@ -225,7 +225,7 @@ export default defineConfig({
{ label: 'Socket API', translations: { ja: 'ソケット API', 'zh-CN': 'Socket API' }, slug: 'docs/socket-api' },
{ label: 'Integrations', translations: { ja: 'インテグレーション', 'zh-CN': '集成' }, slug: 'docs/integrations' },
{ label: 'Agent skill file', translations: { ja: 'エージェントスキルファイル', 'zh-CN': '智能体技能文件' }, slug: 'docs/agent-skill' },
- { label: 'Windows beta', translations: { ja: 'Windows ベータ', 'zh-CN': 'Windows 测试版' }, slug: 'docs/windows-beta' },
+ { label: 'Windows support', translations: { ja: 'Windows サポート', 'zh-CN': 'Windows 支持' }, slug: 'docs/windows-beta' },
],
},
{
diff --git a/website/index.html b/website/index.html
index b241c1b7..06750444 100644
--- a/website/index.html
+++ b/website/index.html
@@ -146,7 +146,7 @@
<button type="button" id="copy-btn" aria-label="Copy install command">copy</button>
</div>
</div>
- <div class="meta">macOS · Linux · Windows beta · Apache 2.0 &nbsp;—&nbsp; <a href="/docs/install/">windows, homebrew, nix and manual install →</a></div>
+ <div class="meta">macOS · Linux · Windows · Apache 2.0 &nbsp;—&nbsp; <a href="/docs/install/">windows, homebrew, nix and manual install →</a></div>
<div class="meta yc-meta"><a class="yc" href="/blog/herdr-is-joining-y-combinator/">backed by <img src="/assets/yc-logo.svg" alt="Y" width="13" height="13" /> Combinator</a></div>
</div>
</header>
@@ -434,7 +434,7 @@
<div class="n"><span>04</span></div>
<div class="cap-in">
<h3>Runs what you already run.&nbsp;<b class="arw">&#8594;</b></h3>
- <p>Claude Code, Codex, Cursor, opencode, Grok and the rest. Herdr doesn't wrap them or replace them, it just owns their terminals — one binary, macOS and Linux, Windows in beta.</p>
+ <p>Claude Code, Codex, Cursor, opencode, Grok and the rest. Herdr doesn't wrap them or replace them, it just owns their terminals — one binary for macOS, Linux, and Windows.</p>
</div>
<div class="ev">
<div class="herd">
@@ -475,7 +475,7 @@
<button type="button" id="copy-btn-2" aria-label="Copy install command">copy</button>
</div>
</div>
- <div class="meta">Windows beta: <code>irm https://herdr.dev/install.ps1 | iex</code> &nbsp;—&nbsp; <a href="/docs/">all install methods →</a></div>
+ <div class="meta">Windows: <code>irm https://herdr.dev/install.ps1 | iex</code> &nbsp;—&nbsp; <a href="/docs/">all install methods →</a></div>
</div>
</section>
diff --git a/website/install.ps1 b/website/install.ps1
index cef4af04..9dacfaa9 100644
--- a/website/install.ps1
+++ b/website/install.ps1
@@ -15,12 +15,9 @@ Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
-if ([string]::IsNullOrWhiteSpace($Channel)) {
- $Channel = "preview"
-}
-
-if ($Channel -notin @("stable", "preview")) {
- Write-Error "Invalid Herdr channel '$Channel'. Use 'preview'."
+$channelWasExplicit = -not [string]::IsNullOrWhiteSpace($Channel)
+if ($channelWasExplicit -and $Channel -notin @("stable", "preview")) {
+ Write-Error "Invalid Herdr channel '$Channel'. Use 'stable' or 'preview'."
exit 1
}
@@ -406,6 +403,33 @@ function Move-DirectoryWithRetry {
}
}
+function Remove-DirectoryWithRetry {
+ param(
+ [string]$Path,
+ [int]$TimeoutMilliseconds = 5000
+ )
+
+ $fullPath = [System.IO.Path]::GetFullPath($Path)
+ $extendedPath = if ($fullPath.StartsWith("\\")) {
+ "\\?\UNC\" + $fullPath.TrimStart([char]'\')
+ } else {
+ "\\?\" + $fullPath
+ }
+ $deadline = [DateTime]::UtcNow.AddMilliseconds($TimeoutMilliseconds)
+ while (Test-Path -LiteralPath $Path) {
+ try {
+ [System.IO.Directory]::Delete($extendedPath, $true)
+ return
+ } catch {
+ if ([DateTime]::UtcNow -ge $deadline) {
+ Write-WarningStep "Herdr installed successfully but could not remove a temporary release backup at $Path."
+ return
+ }
+ Start-Sleep -Milliseconds 100
+ }
+ }
+}
+
function Invoke-WithInstallLock {
param(
[string]$LockPath,
@@ -579,11 +603,6 @@ if (-not [Environment]::Is64BitOperatingSystem) {
exit 1
}
-if ($Channel -eq "stable") {
- Write-Error "Windows builds are preview-only for now. Omit -Channel or use -Channel preview."
- exit 1
-}
-
$architecture = [System.Runtime.InteropServices.RuntimeInformation,mscorlib]::OSArchitecture.ToString()
switch ($architecture) {
"X64" {
@@ -601,14 +620,6 @@ switch ($architecture) {
}
}
-if (-not $useLocalPackage -and [string]::IsNullOrWhiteSpace($ManifestUrl)) {
- $ManifestUrl = if ($Channel -eq "preview") {
- "https://herdr.dev/preview.json"
- } else {
- "https://herdr.dev/latest.json"
- }
-}
-
$herdrHome = if ([string]::IsNullOrWhiteSpace($env:HERDR_HOME)) {
Join-Path $env:USERPROFILE ".herdr"
} else {
@@ -649,13 +660,57 @@ if ($useLocalPackage) {
Format = $LocalPackageFormat
}
} else {
+ if (-not $channelWasExplicit) {
+ if (-not [string]::IsNullOrWhiteSpace($existingHerdr)) {
+ $detectedChannel = [string](& $existingHerdr channel show 2>$null | Select-Object -Last 1)
+ $detectedChannel = $detectedChannel.Trim()
+ if ($LASTEXITCODE -ne 0 -or $detectedChannel -notin @("stable", "preview")) {
+ throw "Could not determine the existing Herdr update channel. Rerun with -Channel stable or -Channel preview."
+ }
+ $Channel = $detectedChannel
+ Write-Step "Preserving existing Herdr $Channel channel"
+ } elseif (-not [string]::IsNullOrWhiteSpace($ManifestUrl) -and $ManifestUrl -match "/preview\.json$") {
+ $Channel = "preview"
+ } else {
+ $Channel = "stable"
+ }
+ }
+
+ if ([string]::IsNullOrWhiteSpace($ManifestUrl)) {
+ $ManifestUrl = if ($Channel -eq "preview") {
+ "https://herdr.dev/preview.json"
+ } else {
+ "https://herdr.dev/latest.json"
+ }
+ }
+
Write-Step "Fetching Herdr $Channel manifest"
$manifest = ConvertTo-ManifestObject -Manifest (Invoke-RestMethod -Uri $ManifestUrl)
+ $manifestChannelProperty = $manifest.PSObject.Properties["channel"]
+ if (-not $channelWasExplicit -and $null -ne $manifestChannelProperty -and [string]$manifestChannelProperty.Value -eq "preview") {
+ $Channel = "preview"
+ }
+ $assetsProperty = $manifest.PSObject.Properties["assets"]
+ $assetProperty = if ($null -eq $assetsProperty) {
+ $null
+ } else {
+ $assetsProperty.Value.PSObject.Properties[$target]
+ }
+ if ($null -eq $assetProperty -and
+ -not $channelWasExplicit -and
+ $Channel -eq "stable" -and
+ $ManifestUrl -match "/latest\.json$") {
+ Write-WarningStep "The stable manifest does not include Windows yet; using preview during the stable-channel rollout."
+ $Channel = "preview"
+ $ManifestUrl = $ManifestUrl.Substring(0, $ManifestUrl.Length - "latest.json".Length) + "preview.json"
+ Write-Step "Fetching Herdr preview manifest"
+ $manifest = ConvertTo-ManifestObject -Manifest (Invoke-RestMethod -Uri $ManifestUrl)
+ }
+ $asset = Get-ManifestAsset -Manifest $manifest -Target $target
if (-not [string]::IsNullOrWhiteSpace($ExpectedBuildId) -and [string]$manifest.build_id -ne $ExpectedBuildId) {
throw "Preview manifest changed while updating. Expected build $ExpectedBuildId but found $($manifest.build_id). Run herdr update again."
}
$versionIdentity = Resolve-HerdrVersion -Manifest $manifest -SelectedChannel $Channel
- $asset = Get-ManifestAsset -Manifest $manifest -Target $target
}
$safeVersionIdentity = $versionIdentity -replace '[^0-9A-Za-z._-]', '-'
$releaseName = "$safeVersionIdentity-$targetTriple"
@@ -710,9 +765,6 @@ try {
Write-WarningStep "Windows could not activate the downloaded release. Another process may have a package file open, such as antivirus or indexing. No incomplete release was activated. Run herdr update again."
throw
}
- if ($null -ne $backupDir) {
- Remove-Item -LiteralPath $backupDir -Recurse -Force -ErrorAction SilentlyContinue
- }
}
$releaseHerdr = Join-Path $releaseDir "herdr.exe"
@@ -721,7 +773,7 @@ try {
throw "Installed Herdr command failed verification: $releaseHerdr --version"
}
Get-ChildItem -LiteralPath $releasesDir -Force -Directory -Filter ".backup.$releaseName.*" -ErrorAction SilentlyContinue |
- Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
+ ForEach-Object { Remove-DirectoryWithRetry -Path $_.FullName }
Set-ManagedJunction -LinkPath $currentDir -TargetPath $releaseDir -ManagedTargetPrefix $releasesDir
Set-ManagedJunction -LinkPath $visibleBinDir -TargetPath $releaseDir -ManagedTargetPrefix $standaloneRoot -AllowLegacyHerdrBinMigration $allowLegacyVisibleBinMigration