From 404c8b5469e5904bd0ec869038ce77efb33befd6 Mon Sep 17 00:00:00 2001 From: Advait Paliwal Date: Thu, 26 Mar 2026 18:17:48 -0700 Subject: [PATCH] Unify installers on tagged releases --- .github/workflows/publish.yml | 42 +----------------- CHANGELOG.md | 9 ++++ README.md | 2 + scripts/install/install-skills.ps1 | 31 ++++++------- scripts/install/install-skills.sh | 23 +++++----- scripts/install/install.ps1 | 44 ++++++------------- scripts/install/install.sh | 41 ++++------------- website/public/install | 41 ++++------------- website/public/install-skills | 23 +++++----- website/public/install-skills.ps1 | 31 ++++++------- website/public/install.ps1 | 44 ++++++------------- .../docs/getting-started/installation.md | 12 ++--- 12 files changed, 112 insertions(+), 231 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6ee379d..90c3e8e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -52,6 +52,7 @@ jobs: build-native-bundles: needs: version-check + if: needs.version-check.outputs.should_publish == 'true' strategy: fail-fast: false matrix: @@ -97,47 +98,6 @@ jobs: name: native-${{ matrix.id }} path: dist/release/* - release-edge: - needs: - - version-check - - build-native-bundles - if: needs.build-native-bundles.result == 'success' - runs-on: blacksmith-4vcpu-ubuntu-2404 - permissions: - contents: write - steps: - - uses: actions/download-artifact@v4 - with: - path: release-assets - merge-multiple: true - - shell: bash - env: - GH_REPO: ${{ github.repository }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - VERSION: ${{ needs.version-check.outputs.version }} - run: | - NOTES="Rolling Feynman bundles from main for the curl/PowerShell installer." - if gh release view edge >/dev/null 2>&1; then - gh release view edge --json assets --jq '.assets[].name' | while IFS= read -r asset; do - [ -n "$asset" ] || continue - gh release delete-asset edge "$asset" --yes - done - gh release upload edge release-assets/* - gh release edit edge \ - --title "edge" \ - --notes "$NOTES" \ - --prerelease \ - --draft=false \ - --target "$GITHUB_SHA" - else - gh release create edge release-assets/* \ - --title "edge" \ - --notes "$NOTES" \ - --prerelease \ - --latest=false \ - --target "$GITHUB_SHA" - fi - release-github: needs: - version-check diff --git a/CHANGELOG.md b/CHANGELOG.md index a44c8ad..6351f4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,3 +59,12 @@ Use this file to track chronology, not release notes. Keep entries short, factua - Failed / learned: PowerShell installer behavior was not executed locally because PowerShell is not installed in this environment. - Blockers: None for the Unix installer flow; Windows remains syntax-only by inspection. - Next: If users want this exposed more prominently, add a dedicated docs/reference page and a homepage-specific skills-only CTA instead of a text link. + +### 2026-03-26 18:08 PDT — installer-release-unification + +- Objective: Remove the moving `edge` installer channel and unify installs on tagged releases only. +- Changed: Updated `scripts/install/install.sh`, `scripts/install/install.ps1`, `scripts/install/install-skills.sh`, and `scripts/install/install-skills.ps1` so the default target is the latest tagged release, latest-version resolution uses public GitHub release pages instead of `api.github.com`, and explicit `edge` requests now fail with a removal message; removed the `release-edge` job from `.github/workflows/publish.yml`; updated `README.md` and `website/src/content/docs/getting-started/installation.md`; re-synced `website/public/install*`. +- Verified: Ran `sh -n` on the Unix installer copies; confirmed `sh scripts/install/install.sh edge` and `sh scripts/install/install-skills.sh edge --dir ` fail with the intended removal message; executed `sh scripts/install/install.sh` into temp dirs and confirmed the installed binary reports `0.2.14`; executed `sh scripts/install/install-skills.sh --dir ` and confirmed extracted `SKILL.md` files; ran `cd website && npm run build`. +- Failed / learned: The install failure was caused by unauthenticated GitHub API rate limiting on the `edge` path, so renaming channels without removing the API dependency would not have fixed the root cause. +- Blockers: `npm run build` still emits a pre-existing duplicate-content warning for `getting-started/installation`; the build succeeds. +- Next: If desired, remove the now-unused `stable` alias too and clean up the duplicate docs-content warning separately. diff --git a/README.md b/README.md index 25af8af..bb67de6 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ curl -fsSL https://feynman.is/install | bash irm https://feynman.is/install.ps1 | iex ``` +The one-line installer fetches the latest tagged release. To pin a version, pass it explicitly, for example `curl -fsSL https://feynman.is/install | bash -s -- 0.2.14`. + If you install via `pnpm` or `bun` instead of the standalone bundle, Feynman requires Node.js `20.19.0` or newer. ### Skills Only diff --git a/scripts/install/install-skills.ps1 b/scripts/install/install-skills.ps1 index 3fe5ad1..c650efa 100644 --- a/scripts/install/install-skills.ps1 +++ b/scripts/install/install-skills.ps1 @@ -1,5 +1,5 @@ param( - [string]$Version = "edge", + [string]$Version = "latest", [ValidateSet("User", "Repo")] [string]$Scope = "User", [string]$TargetDir = "" @@ -11,37 +11,34 @@ function Normalize-Version { param([string]$RequestedVersion) if (-not $RequestedVersion) { - return "edge" + return "latest" } switch ($RequestedVersion.ToLowerInvariant()) { - "edge" { return "edge" } "latest" { return "latest" } "stable" { return "latest" } + "edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." } default { return $RequestedVersion.TrimStart("v") } } } +function Resolve-LatestReleaseVersion { + $page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest" + $match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)') + if (-not $match.Success) { + throw "Failed to resolve the latest Feynman release version." + } + + return $match.Groups[1].Value +} + function Resolve-VersionMetadata { param([string]$RequestedVersion) $normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion - if ($normalizedVersion -eq "edge") { - return [PSCustomObject]@{ - ResolvedVersion = "edge" - GitRef = "main" - DownloadUrl = "https://github.com/getcompanion-ai/feynman/archive/refs/heads/main.zip" - } - } - if ($normalizedVersion -eq "latest") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest" - if (-not $release.tag_name) { - throw "Failed to resolve the latest Feynman release version." - } - - $resolvedVersion = $release.tag_name.TrimStart("v") + $resolvedVersion = Resolve-LatestReleaseVersion } else { $resolvedVersion = $normalizedVersion } diff --git a/scripts/install/install-skills.sh b/scripts/install/install-skills.sh index f7bf224..0e1df44 100644 --- a/scripts/install/install-skills.sh +++ b/scripts/install/install-skills.sh @@ -2,7 +2,7 @@ set -eu -VERSION="edge" +VERSION="latest" SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}" TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}" @@ -12,12 +12,16 @@ step() { normalize_version() { case "$1" in - "" | edge) - printf 'edge\n' + "") + printf 'latest\n' ;; latest | stable) printf 'latest\n' ;; + edge) + echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2 + exit 1 + ;; v*) printf '%s\n' "${1#v}" ;; @@ -73,14 +77,9 @@ download_text() { resolve_version() { normalized_version="$(normalize_version "$VERSION")" - if [ "$normalized_version" = "edge" ]; then - printf 'edge\nmain\n' - return - fi - if [ "$normalized_version" = "latest" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")" - resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)" + release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")" + resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)" if [ -z "$resolved_version" ]; then echo "Failed to resolve the latest Feynman release version." >&2 @@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do ;; --dir) if [ $# -lt 2 ]; then - echo "Usage: install-skills.sh [edge|stable|latest|] [--user|--repo] [--dir ]" >&2 + echo "Usage: install-skills.sh [stable|latest|] [--user|--repo] [--dir ]" >&2 exit 1 fi TARGET_DIR="$2" @@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do ;; *) echo "Unknown argument: $1" >&2 - echo "Usage: install-skills.sh [edge|stable|latest|] [--user|--repo] [--dir ]" >&2 + echo "Usage: install-skills.sh [stable|latest|] [--user|--repo] [--dir ]" >&2 exit 1 ;; esac diff --git a/scripts/install/install.ps1 b/scripts/install/install.ps1 index c75b672..865c0c7 100644 --- a/scripts/install/install.ps1 +++ b/scripts/install/install.ps1 @@ -1,5 +1,5 @@ param( - [string]$Version = "edge" + [string]$Version = "latest" ) $ErrorActionPreference = "Stop" @@ -8,17 +8,27 @@ function Normalize-Version { param([string]$RequestedVersion) if (-not $RequestedVersion) { - return "edge" + return "latest" } switch ($RequestedVersion.ToLowerInvariant()) { - "edge" { return "edge" } "latest" { return "latest" } "stable" { return "latest" } + "edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." } default { return $RequestedVersion.TrimStart("v") } } } +function Resolve-LatestReleaseVersion { + $page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest" + $match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)') + if (-not $match.Success) { + throw "Failed to resolve the latest Feynman release version." + } + + return $match.Groups[1].Value +} + function Resolve-ReleaseMetadata { param( [string]$RequestedVersion, @@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata { $normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion - if ($normalizedVersion -eq "edge") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge" - $asset = $release.assets | Where-Object { $_.name -like "feynman-*-$AssetTarget.$BundleExtension" } | Select-Object -First 1 - if (-not $asset) { - throw "Failed to resolve the latest Feynman edge bundle." - } - - $archiveName = $asset.name - $suffix = ".$BundleExtension" - $bundleName = $archiveName.Substring(0, $archiveName.Length - $suffix.Length) - $resolvedVersion = $bundleName.Substring("feynman-".Length) - $resolvedVersion = $resolvedVersion.Substring(0, $resolvedVersion.Length - ("-$AssetTarget").Length) - - return [PSCustomObject]@{ - ResolvedVersion = $resolvedVersion - BundleName = $bundleName - ArchiveName = $archiveName - DownloadUrl = $asset.browser_download_url - } - } - if ($normalizedVersion -eq "latest") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest" - if (-not $release.tag_name) { - throw "Failed to resolve the latest Feynman release version." - } - - $resolvedVersion = $release.tag_name.TrimStart("v") + $resolvedVersion = Resolve-LatestReleaseVersion } else { $resolvedVersion = $normalizedVersion } diff --git a/scripts/install/install.sh b/scripts/install/install.sh index f8d7e9b..23b4427 100644 --- a/scripts/install/install.sh +++ b/scripts/install/install.sh @@ -2,7 +2,7 @@ set -eu -VERSION="${1:-edge}" +VERSION="${1:-latest}" INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}" INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}" SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}" @@ -54,12 +54,16 @@ run_with_spinner() { normalize_version() { case "$1" in - "" | edge) - printf 'edge\n' + "") + printf 'latest\n' ;; latest | stable) printf 'latest\n' ;; + edge) + echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2 + exit 1 + ;; v*) printf '%s\n' "${1#v}" ;; @@ -184,36 +188,9 @@ warn_command_conflict() { resolve_release_metadata() { normalized_version="$(normalize_version "$VERSION")" - if [ "$normalized_version" = "edge" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge")" - asset_url="" - - for candidate in $(printf '%s\n' "$release_json" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\)".*/\1/p'); do - case "$candidate" in - */feynman-*-${asset_target}.${archive_extension}) - asset_url="$candidate" - break - ;; - esac - done - - if [ -z "$asset_url" ]; then - echo "Failed to resolve the latest Feynman edge bundle." >&2 - exit 1 - fi - - archive_name="${asset_url##*/}" - bundle_name="${archive_name%.$archive_extension}" - resolved_version="${bundle_name#feynman-}" - resolved_version="${resolved_version%-${asset_target}}" - - printf '%s\n%s\n%s\n%s\n' "$resolved_version" "$bundle_name" "$archive_name" "$asset_url" - return - fi - if [ "$normalized_version" = "latest" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")" - resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)" + release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")" + resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)" if [ -z "$resolved_version" ]; then echo "Failed to resolve the latest Feynman release version." >&2 diff --git a/website/public/install b/website/public/install index f8d7e9b..23b4427 100644 --- a/website/public/install +++ b/website/public/install @@ -2,7 +2,7 @@ set -eu -VERSION="${1:-edge}" +VERSION="${1:-latest}" INSTALL_BIN_DIR="${FEYNMAN_INSTALL_BIN_DIR:-$HOME/.local/bin}" INSTALL_APP_DIR="${FEYNMAN_INSTALL_APP_DIR:-$HOME/.local/share/feynman}" SKIP_PATH_UPDATE="${FEYNMAN_INSTALL_SKIP_PATH_UPDATE:-0}" @@ -54,12 +54,16 @@ run_with_spinner() { normalize_version() { case "$1" in - "" | edge) - printf 'edge\n' + "") + printf 'latest\n' ;; latest | stable) printf 'latest\n' ;; + edge) + echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2 + exit 1 + ;; v*) printf '%s\n' "${1#v}" ;; @@ -184,36 +188,9 @@ warn_command_conflict() { resolve_release_metadata() { normalized_version="$(normalize_version "$VERSION")" - if [ "$normalized_version" = "edge" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge")" - asset_url="" - - for candidate in $(printf '%s\n' "$release_json" | sed -n 's/.*"browser_download_url":[[:space:]]*"\([^"]*\)".*/\1/p'); do - case "$candidate" in - */feynman-*-${asset_target}.${archive_extension}) - asset_url="$candidate" - break - ;; - esac - done - - if [ -z "$asset_url" ]; then - echo "Failed to resolve the latest Feynman edge bundle." >&2 - exit 1 - fi - - archive_name="${asset_url##*/}" - bundle_name="${archive_name%.$archive_extension}" - resolved_version="${bundle_name#feynman-}" - resolved_version="${resolved_version%-${asset_target}}" - - printf '%s\n%s\n%s\n%s\n' "$resolved_version" "$bundle_name" "$archive_name" "$asset_url" - return - fi - if [ "$normalized_version" = "latest" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")" - resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)" + release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")" + resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)" if [ -z "$resolved_version" ]; then echo "Failed to resolve the latest Feynman release version." >&2 diff --git a/website/public/install-skills b/website/public/install-skills index f7bf224..0e1df44 100644 --- a/website/public/install-skills +++ b/website/public/install-skills @@ -2,7 +2,7 @@ set -eu -VERSION="edge" +VERSION="latest" SCOPE="${FEYNMAN_SKILLS_SCOPE:-user}" TARGET_DIR="${FEYNMAN_SKILLS_DIR:-}" @@ -12,12 +12,16 @@ step() { normalize_version() { case "$1" in - "" | edge) - printf 'edge\n' + "") + printf 'latest\n' ;; latest | stable) printf 'latest\n' ;; + edge) + echo "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." >&2 + exit 1 + ;; v*) printf '%s\n' "${1#v}" ;; @@ -73,14 +77,9 @@ download_text() { resolve_version() { normalized_version="$(normalize_version "$VERSION")" - if [ "$normalized_version" = "edge" ]; then - printf 'edge\nmain\n' - return - fi - if [ "$normalized_version" = "latest" ]; then - release_json="$(download_text "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest")" - resolved_version="$(printf '%s\n' "$release_json" | sed -n 's/.*"tag_name":[[:space:]]*"v\([^"]*\)".*/\1/p' | head -n 1)" + release_page="$(download_text "https://github.com/getcompanion-ai/feynman/releases/latest")" + resolved_version="$(printf '%s\n' "$release_page" | sed -n 's@.*releases/tag/v\([0-9][^"<>[:space:]]*\).*@\1@p' | head -n 1)" if [ -z "$resolved_version" ]; then echo "Failed to resolve the latest Feynman release version." >&2 @@ -125,7 +124,7 @@ while [ $# -gt 0 ]; do ;; --dir) if [ $# -lt 2 ]; then - echo "Usage: install-skills.sh [edge|stable|latest|] [--user|--repo] [--dir ]" >&2 + echo "Usage: install-skills.sh [stable|latest|] [--user|--repo] [--dir ]" >&2 exit 1 fi TARGET_DIR="$2" @@ -136,7 +135,7 @@ while [ $# -gt 0 ]; do ;; *) echo "Unknown argument: $1" >&2 - echo "Usage: install-skills.sh [edge|stable|latest|] [--user|--repo] [--dir ]" >&2 + echo "Usage: install-skills.sh [stable|latest|] [--user|--repo] [--dir ]" >&2 exit 1 ;; esac diff --git a/website/public/install-skills.ps1 b/website/public/install-skills.ps1 index 3fe5ad1..c650efa 100644 --- a/website/public/install-skills.ps1 +++ b/website/public/install-skills.ps1 @@ -1,5 +1,5 @@ param( - [string]$Version = "edge", + [string]$Version = "latest", [ValidateSet("User", "Repo")] [string]$Scope = "User", [string]$TargetDir = "" @@ -11,37 +11,34 @@ function Normalize-Version { param([string]$RequestedVersion) if (-not $RequestedVersion) { - return "edge" + return "latest" } switch ($RequestedVersion.ToLowerInvariant()) { - "edge" { return "edge" } "latest" { return "latest" } "stable" { return "latest" } + "edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." } default { return $RequestedVersion.TrimStart("v") } } } +function Resolve-LatestReleaseVersion { + $page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest" + $match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)') + if (-not $match.Success) { + throw "Failed to resolve the latest Feynman release version." + } + + return $match.Groups[1].Value +} + function Resolve-VersionMetadata { param([string]$RequestedVersion) $normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion - if ($normalizedVersion -eq "edge") { - return [PSCustomObject]@{ - ResolvedVersion = "edge" - GitRef = "main" - DownloadUrl = "https://github.com/getcompanion-ai/feynman/archive/refs/heads/main.zip" - } - } - if ($normalizedVersion -eq "latest") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest" - if (-not $release.tag_name) { - throw "Failed to resolve the latest Feynman release version." - } - - $resolvedVersion = $release.tag_name.TrimStart("v") + $resolvedVersion = Resolve-LatestReleaseVersion } else { $resolvedVersion = $normalizedVersion } diff --git a/website/public/install.ps1 b/website/public/install.ps1 index c75b672..865c0c7 100644 --- a/website/public/install.ps1 +++ b/website/public/install.ps1 @@ -1,5 +1,5 @@ param( - [string]$Version = "edge" + [string]$Version = "latest" ) $ErrorActionPreference = "Stop" @@ -8,17 +8,27 @@ function Normalize-Version { param([string]$RequestedVersion) if (-not $RequestedVersion) { - return "edge" + return "latest" } switch ($RequestedVersion.ToLowerInvariant()) { - "edge" { return "edge" } "latest" { return "latest" } "stable" { return "latest" } + "edge" { throw "The edge channel has been removed. Use the default installer for the latest tagged release or pass an exact version." } default { return $RequestedVersion.TrimStart("v") } } } +function Resolve-LatestReleaseVersion { + $page = Invoke-WebRequest -Uri "https://github.com/getcompanion-ai/feynman/releases/latest" + $match = [regex]::Match($page.Content, 'releases/tag/v([0-9][^"''<>\s]*)') + if (-not $match.Success) { + throw "Failed to resolve the latest Feynman release version." + } + + return $match.Groups[1].Value +} + function Resolve-ReleaseMetadata { param( [string]$RequestedVersion, @@ -28,34 +38,8 @@ function Resolve-ReleaseMetadata { $normalizedVersion = Normalize-Version -RequestedVersion $RequestedVersion - if ($normalizedVersion -eq "edge") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/tags/edge" - $asset = $release.assets | Where-Object { $_.name -like "feynman-*-$AssetTarget.$BundleExtension" } | Select-Object -First 1 - if (-not $asset) { - throw "Failed to resolve the latest Feynman edge bundle." - } - - $archiveName = $asset.name - $suffix = ".$BundleExtension" - $bundleName = $archiveName.Substring(0, $archiveName.Length - $suffix.Length) - $resolvedVersion = $bundleName.Substring("feynman-".Length) - $resolvedVersion = $resolvedVersion.Substring(0, $resolvedVersion.Length - ("-$AssetTarget").Length) - - return [PSCustomObject]@{ - ResolvedVersion = $resolvedVersion - BundleName = $bundleName - ArchiveName = $archiveName - DownloadUrl = $asset.browser_download_url - } - } - if ($normalizedVersion -eq "latest") { - $release = Invoke-RestMethod -Uri "https://api.github.com/repos/getcompanion-ai/feynman/releases/latest" - if (-not $release.tag_name) { - throw "Failed to resolve the latest Feynman release version." - } - - $resolvedVersion = $release.tag_name.TrimStart("v") + $resolvedVersion = Resolve-LatestReleaseVersion } else { $resolvedVersion = $normalizedVersion } diff --git a/website/src/content/docs/getting-started/installation.md b/website/src/content/docs/getting-started/installation.md index 907a9b4..2c1e0a6 100644 --- a/website/src/content/docs/getting-started/installation.md +++ b/website/src/content/docs/getting-started/installation.md @@ -19,8 +19,6 @@ The installer detects your OS and architecture automatically. On macOS it suppor If you previously installed Feynman via `npm`, `pnpm`, or `bun` and still see local Node.js errors after a curl install, your shell is probably still resolving the older global binary first. Run `which -a feynman`, then `hash -r`, or launch the standalone shim directly with `~/.local/bin/feynman`. -By default, the one-line installer tracks the rolling `edge` channel from `main`. - On **Windows**, open PowerShell as Administrator and run: ```powershell @@ -59,22 +57,20 @@ Or install them repo-locally: These installers download only the `skills/` tree from the Feynman repository. They do not install the Feynman terminal, bundled Node runtime, auth storage, or Pi packages. -## Stable or pinned releases +## Pinned releases -If you want the latest tagged release instead of the rolling `edge` channel: +The one-line installer already targets the latest tagged release. To pin an exact version, pass it explicitly: ```bash -curl -fsSL https://feynman.is/install | bash -s -- stable +curl -fsSL https://feynman.is/install | bash -s -- 0.2.14 ``` On Windows: ```powershell -& ([scriptblock]::Create((irm https://feynman.is/install.ps1))) -Version stable +& ([scriptblock]::Create((irm https://feynman.is/install.ps1))) -Version 0.2.14 ``` -You can also pin an exact version by replacing `stable` with a version such as `0.2.14`. - ## pnpm If you already have Node.js `20.19.0` or newer installed, you can install Feynman globally via `pnpm`: