Skip to content

feat(install): standalone curl/irm one-liner installers#45

Merged
MasonStation merged 2 commits intomainfrom
feat/standalone-installers
Apr 27, 2026
Merged

feat(install): standalone curl/irm one-liner installers#45
MasonStation merged 2 commits intomainfrom
feat/standalone-installers

Conversation

@MasonStation
Copy link
Copy Markdown
Contributor

Summary

Adds scripts/install.sh and scripts/install.ps1 so users can install phantom directly from a GitHub release, without depending on bun add -g phantom-secrets / npm i -g phantom-secrets.

Why

Three real problems with the npm-wrapper-only path, surfaced while debugging a fresh-Windows-machine install of ashlr-stack (which depends on phantom):

  1. Lazy download. npm/bin/cli.js only downloads the real Rust binary on first invocation. So a successful npm i -g phantom-secrets leaves phantom uninstalled until someone actually runs it. Tools that detect-and-use phantom right after install (e.g. Stack's installer) can't rely on it.

  2. Bun-on-Windows shim non-generation. Verified by reproducing on a clean Win11 machine: bun add -g phantom-secrets exits 0 and reports "installed phantom-secrets@0.4.0 with binaries: phantom, phantom-secrets" — but ~\.bun\bin\ afterwards contains only bun.exe. The shims from the package's bin field never get written. So phantom isn't on PATH even after a "successful" install.

  3. Registry/GitHub version skew. npm latest: 0.4.0. GitHub Releases latest: v0.5.1. Users on bun add -g phantom-secrets are getting an older release than people running curl one-liners. Worth publishing 0.5.1 to npm separately, but a direct-from-releases path keeps users current regardless.

What the installers do

  • Resolve latest release tag via the GitHub API (or honor $PHANTOM_TAG)
  • Download phantom-<target>.{tar.gz|zip} + the .sha256 sidecar
  • Verify SHA-256 (refuse on mismatch or missing sidecar — won't install unverified binary)
  • Extract to ~/.phantom-secrets/bin (or $PHANTOM_INSTALL_DIR)
  • install.sh: idempotently appends to the user's shell rc (zsh/bash/fish), using a # phantom-secrets PATH marker so re-runs are no-ops. Same helper pattern Stack uses.
  • install.ps1: writes User-scope PATH via [Environment]::SetEnvironmentVariable, also injects into $env:Path for the current session so phantom --help works without opening a new shell. Calls Unblock-File on the extracted *.exe to clear MOTW before first run.

Suggested follow-up (not in this PR)

  • Host these at https://phm.dev/install.{sh,ps1} so users can run curl -fsSL https://phm.dev/install.sh | bash / irm https://phm.dev/install.ps1 | iex (matches Stack's pattern). Either an Astro/Cloudflare deploy of these files, or a redirect from the marketing site.
  • Publish v0.5.1 to npm to close the registry/GitHub skew.
  • Investigate why v0.5.1 Windows binary trips An Application Control policy has blocked this file on at least one Win11 install — hit during installer testing. Both v0.5.0 and v0.5.1 are unsigned, so it's not signing; likely Smart App Control reputation. Worth looking at from the build/release side.
  • The bin field shims not generating under bun on Windows is upstream — should be reported to oven-sh/bun.

Test plan

  • Run scripts/install.sh on a fresh Linux box, verify phantom --help works in a new shell
  • Run on macOS (both arm64 and x64) — verify target detection picks the right archive
  • Run scripts/install.ps1 on a fresh Windows VM with no prior phantom install — verify the binary runs in the same session via $env:Path injection
  • Re-run on a system that already has phantom — verify the # phantom-secrets PATH marker prevents duplicate rc entries
  • Test PHANTOM_TAG=v0.4.0 ./scripts/install.sh (pin to older release)

🤖 Generated with Claude Code

Adds scripts/install.sh and scripts/install.ps1 so users can install
phantom directly from a release artifact, without depending on
`bun add -g phantom-secrets` / `npm i -g phantom-secrets`.

Why this matters:

- The npm wrapper (npm/bin/cli.js) lazy-downloads on first run, so a
  "successful" `npm i -g` still leaves the binary uninstalled until
  `phantom` is invoked. That makes downstream tools (e.g. Stack)
  unable to reliably detect or use phantom right after install.
- Bun-on-Windows in particular doesn't reliably materialize the
  `phantom`/`phantom-secrets` shims from the npm package's `bin`
  field, so even a clean `bun add -g phantom-secrets` exit-0 leaves
  `~\.bun\bin` containing only `bun.exe`.
- The npm registry currently lags behind GitHub Releases (npm latest:
  0.4.0; GitHub Releases latest: 0.5.1). Curl/irm hits the GitHub
  release directly so users always get the latest.

What the installers do:

- Resolve latest release tag via `api.github.com/.../releases/latest`
  (or honor `$PHANTOM_TAG` to pin a version)
- Download `phantom-<target>.{tar.gz|zip}` and the `.sha256` sidecar
- Verify SHA-256 (refuses to install on mismatch or missing sidecar)
- Extract to `~/.phantom-secrets/bin` (or `$PHANTOM_INSTALL_DIR`)
- install.sh: idempotently appends to the user's shell rc
  (zsh/bash/fish) with a `# phantom-secrets PATH` marker so re-runs
  are no-ops
- install.ps1: writes User-scope PATH via `SetEnvironmentVariable`,
  also injects into `$env:Path` for the current session, and runs
  `Unblock-File` on extracted binaries to clear MOTW for SmartScreen

Suggested next step (out of scope here): host these at
`https://phm.dev/install.{sh,ps1}` so users can run:

  curl -fsSL https://phm.dev/install.sh | bash
  irm https://phm.dev/install.ps1 | iex

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
web Ready Ready Preview, Comment Apr 26, 2026 8:06pm

Request Review

Mirrors scripts/install.{sh,ps1} into apps/web/public/ so they're
reachable as https://phm.dev/install.sh and https://phm.dev/install.ps1
once apps/web deploys to main.

Next.js 15 serves public/* as static assets at site root by default;
no rewrites or headers customization needed. curl/iex don't care about
Content-Type, so the default works for pipe-to-shell consumers.

This unblocks the matching ashlr-stack change that calls these URLs
to install Phantom (ashlr-stack#2).

Note: scripts/ and apps/web/public/ are now duplicate copies. A
future commit should either symlink one into the other or wire a
prebuild copy step in apps/web/package.json.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MasonStation
Copy link
Copy Markdown
Contributor Author

Added a follow-up commit (3e1d237) mirroring the installers into apps/web/public/ so they get served at https://phm.dev/install.sh and https://phm.dev/install.ps1 once apps/web deploys.

next.config.ts is empty so the default Next.js 15 behavior (public/* → site root) handles this with no further config. curl | bash and irm | iex don't care about Content-Type, so no rewrites or headers needed.

This is what unblocks the matching ashlr-stack#2 change (which calls these URLs at install time). Suggested merge order:

  1. This PR (phantom-secrets#45) → land + deploy apps/web so the URLs are live
  2. ashlr-stack#1 (PATH auto-add)
  3. ashlr-stack#2 (Phantom handoff to phm.dev)

Heads up: scripts/install.{sh,ps1} and apps/web/public/install.{sh,ps1} are now duplicate copies. Worth a follow-up to either symlink or add a prebuild step in apps/web/package.json that copies from scripts/. Same gap exists in ashlr-stack between scripts/ and packages/site/public/.

@MasonStation MasonStation merged commit 494d351 into main Apr 27, 2026
6 checks passed
@MasonStation MasonStation deleted the feat/standalone-installers branch April 27, 2026 17:46
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.

1 participant