Skip to content

feat: standalone add-sg-mcp binaries and install scripts for macOS, Linux and Windows - #6

Open
arunim2405 wants to merge 8 commits into
feat/auth-grantfrom
feat/binaries
Open

arunim2405 wants to merge 8 commits into
feat/auth-grantfrom
feat/binaries

Conversation

@arunim2405

@arunim2405 arunim2405 commented Sep 18, 2026

Copy link
Copy Markdown
Member

Stacked on #5 (feat/auth-grant).

Why

StackGuardian's users are DevOps and infra engineers, and many of them don't have Node.js, so npx add-sg-mcp fails for them before it starts. With this PR, each GitHub release ships standalone executables (no Node.js, npm or Bun needed) and a one-line installer:

curl -fsSL https://github.com/StackGuardian/add-sg-mcp/releases/latest/download/install.sh | sh
irm https://github.com/StackGuardian/add-sg-mcp/releases/latest/download/install.ps1 | iex

What

Binaries

  • bun run build:binary compiles src/index.ts into one executable with bun build --compile, with the three skills embedded as files.
  • A compiled binary can't cpSync out of Bun's virtual filesystem. So bundledSkillsDir() first writes the embedded skills to a private mkdtemp directory, which is removed on exit, and the installer runs unchanged. The npm package still reads skills/ from disk.

Install scripts

  • install.sh (POSIX sh, macOS and Linux) and install.ps1 (Windows):
    1. Pick the build for the machine. On Apple Silicon they use the native build even from a shell running under Rosetta.
    2. Stop with a pointer to npx on unsupported systems: musl/Alpine (detected by the missing glibc loader), and non-x64 Windows.
    3. Download the archive and SHA256SUMS, and stop before installing anything if the checksum doesn't match.
    4. Install to ~/.local/bin, or on Windows to %LOCALAPPDATA%\add-sg-mcp\bin, which is added to the user PATH.
    5. Run add-sg-mcp, passing through any flags given with sh -s -- … or & ([scriptblock]::Create((irm …))) ….
  • Under curl | sh, the binary reads from /dev/tty, so prompts and the browser sign-in work.
  • install.sh runs everything from main "$@" on its last line, so a cut-off download does nothing.
  • install.ps1 runs inside one scriptblock and never calls exit under iex, so it can't close the user's session.
  • Four environment variables adjust both scripts:
    • ADD_SG_MCP_VERSION picks a release.
    • ADD_SG_MCP_INSTALL_DIR picks where to install.
    • ADD_SG_MCP_DOWNLOAD_URL points at a mirror; http(s) or file://, which helps on machines without internet access.
    • ADD_SG_MCP_NO_RUN=1 installs without running.

.github/workflows/binaries.yml

  • build:
    • Runs shellcheck on install.sh.
    • Cross-compiles darwin-arm64, darwin-x64, linux-arm64, linux-x64 and windows-x64. The x64 builds use Bun's baseline variant, so CPUs and VMs without AVX2 can run them.
    • Packages each as .tar.gz or .zip (binary + LICENSE + NOTICE), and writes SHA256SUMS covering the archives and both scripts.
  • smoke, on each native runner (macos-latest, macos-15-intel, ubuntu-24.04-arm, ubuntu-latest, windows-latest):
    • Verifies the archive's checksum and unpacks it.
    • Runs tests/e2e/sg-binary.test.ts: a real offline install into a throwaway HOME, checking the server entry and the skills.
    • Runs tests/e2e/sg-install-script.test.ts against the real release files: install + run, piped curl | sh form, NO_RUN, and a tampered checksum that must abort.
  • publish runs on release: published or on a manual run with a tag:
    • Checks that the tag matches package.json#version.
    • Attests every file (actions/attest, SLSA provenance) and uploads it to the release.
  • All actions are SHA-pinned, permissions are set per job (only publish can write), and the Bun version is pinned because its runtime ships inside every binary.

release.yml (npm) is unchanged. None of the files kept identical to upstream were touched. CHANGELOG, RELEASING.md and the layout in AGENTS.md are updated.

README rewritten for StackGuardian MCP users: prerequisites (org, region, an agent); install with or without Node.js; how to check it works; what the MCP server's tools and the three skills let an agent do, with example prompts taken from the server's tool descriptions; a comparison of the sign-in modes; everyday tasks; and troubleshooting, with each answer checked against the CLI code. Options, commands, install-script settings, per-agent notes, how it works and security are now under Reference; development notes are at the end. The options list gains --token and --api-base, which the CLI already accepted.

Fix: remove --name keeps the skills. The skills are shared by every StackGuardian-<org> entry, so removing one organization's entry no longer takes them out of your agents. remove without --name, and logout --purge, still remove them. There's a new e2e test for this: two orgs, remove one, and the other entry and the skills stay.

Test plan

  • bun run typecheck; bun run test: 21/21 files, including unit tests for extracting skills, sg-binary (compiles and runs the binary) and sg-install-script (runs install.sh against a release built for this machine)
  • bun run fallow -- --summary: no new findings, apart from the new test file being listed as "unused" like the other e2e tests
  • install.sh passes shellcheck and runs under dash and macOS sh, both as a file and piped
  • binaries.yml green on this PR: build + 5 smoke jobs, each running the binary and the matching install script (install.ps1 on Windows)
  • Publish path exercised twice against a draft release; see the comments

Not in this PR

  • Apple notarization and Windows Authenticode signing. The install scripts aren't affected; browser downloads are quarantined on macOS and may get a SmartScreen prompt on Windows.
  • A Homebrew tap, winget, and Linux musl (Alpine) builds.
  • Binaries are 60–85 MB because the Bun runtime is embedded; the archives are 25–38 MB.

🤖 Generated with Claude Code

arunim2405 and others added 3 commits September 18, 2026 22:44
`bun run build:binary` compiles src/index.ts into a single executable that
needs no Node.js. The skills are embedded as files; a compiled binary cannot
cpSync out of Bun's virtual filesystem, so bundledSkillsDir() first writes the
embedded skills to a private temp directory (removed on exit) and the
installer runs unchanged.

tests/e2e/sg-binary.test.ts compiles the binary and installs into a throwaway
HOME; with ADD_SG_MCP_BINARY it tests a prebuilt executable instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
binaries.yml cross-compiles darwin-arm64, darwin-x64, linux-arm64, linux-x64
and windows-x64 (x64 on Bun's baseline build), runs each archive on its own
OS, and on a published release (or a manual run with a tag) attaches the
archives, SHA256SUMS and build provenance attestations to the release.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Windows checkouts convert the source SKILL.md files to CRLF while the
embedded copies stay LF, so the smoke test compares normalized text.
actions/attest-build-provenance v4 is a wrapper; use actions/attest directly
with the artifact-metadata permission it documents.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@arunim2405

Copy link
Copy Markdown
Member Author

Publish path tested end to end (before merge, since workflow_dispatch only works once the workflow is on main):

  • The throwaway branch ci/binaries-publish-test added a temporary push trigger to this workflow. It published to a draft v0.1.0 release; a draft doesn't fire release: published, so release.yml/npm never ran.
  • Run: https://github.com/StackGuardian/add-sg-mcp/actions/runs/35393375520. Build ✅, the 5 smoke tests ✅, Attach to release ✅.
  • The draft received all 5 archives + SHA256SUMS (darwin-arm64 24.6 MB, darwin-x64 27.2 MB, linux-arm64 35 MB, linux-x64 35 MB, windows-x64 38 MB).
  • Locally, I downloaded add-sg-mcp-darwin-arm64.tar.gz with gh release download:
    • shasum -a 256 -c passes.
    • gh attestation verify … -R StackGuardian/add-sg-mcp passes: SLSA provenance v1, signer .github/workflows/binaries.yml.
    • The extracted binary runs and prints 0.1.0.
  • Afterwards I deleted the draft release and the throwaway branch. The test attestations stay in the attestation store; their signer ref is refs/heads/ci/binaries-publish-test, so they can't be mistaken for release builds.

Run on this PR's head: https://github.com/StackGuardian/add-sg-mcp/actions/runs/35393333010. Build + all 5 smoke tests green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@arunim2405
arunim2405 marked this pull request as ready for review September 18, 2026 21:00
arunim2405 and others added 2 commits September 19, 2026 06:46
`curl -fsSL …/releases/latest/download/install.sh | sh` (macOS, Linux) and
`irm …/install.ps1 | iex` (Windows) pick the build for the machine, verify it
against SHA256SUMS, install it (~/.local/bin, or %LOCALAPPDATA%\add-sg-mcp\bin
added to the user PATH) and run it with any flags passed through. Under
`curl | sh` the binary gets /dev/tty so its prompts work. ADD_SG_MCP_VERSION,
ADD_SG_MCP_INSTALL_DIR, ADD_SG_MCP_DOWNLOAD_URL and ADD_SG_MCP_NO_RUN adjust it.

binaries.yml shellchecks install.sh, attaches both scripts to the release
(listed in SHA256SUMS and attested), and each smoke job runs
tests/e2e/sg-install-script.test.ts against the real archives.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@arunim2405 arunim2405 changed the title feat: standalone add-sg-mcp binaries for macOS, Linux and Windows feat: standalone add-sg-mcp binaries and install scripts for macOS, Linux and Windows Sep 19, 2026
@arunim2405

Copy link
Copy Markdown
Member Author

Install scripts: publish path tested end to end. Same method as before: a throwaway branch published to a draft v0.1.0; both were deleted afterwards.

  • Run: https://github.com/StackGuardian/add-sg-mcp/actions/runs/35422352430. Build (with shellcheck) ✅, the 5 smoke tests (binary + install script on each OS) ✅, Attach to release ✅.
  • The draft received the 5 archives, install.sh, install.ps1 and SHA256SUMS.
  • Checks on the downloaded draft files:
    • All three files pass shasum -c.
    • gh attestation verify install.sh is signed by binaries.yml.
    • The published install.sh is byte-identical to the repo's.
  • Running the published install.sh piped into sh (cat install.sh | sh -s -- --token … --org demo-org --region eu -y -a claude-code, with ADD_SG_MCP_DOWNLOAD_URL pointing at the downloaded files) installed the binary to ~/.local/bin. It wrote StackGuardian-demo-org to .claude.json and installed all three skills.
  • Interactive curl | sh in a pseudo-terminal: the "Where is your StackGuardian account?" region prompt renders. The CLI only prompts when stdin.isTTY is true, so the binary did get /dev/tty while sh was reading the pipe.

Only the real public link …/releases/latest/download/install.sh is left untested; it can only be tried once the first non-draft release exists.

arunim2405 and others added 2 commits September 19, 2026 09:22
Lead with what a StackGuardian user needs: prerequisites (org, region, an
agent), install with or without Node.js, how to check it works, what the MCP
server's tools and the skills let an agent do (with example prompts), a
comparison of the sign-in modes, everyday tasks, and troubleshooting checked
against the CLI's behavior. Options, commands, install-script settings,
per-agent notes, how it works and security move to a Reference section;
development notes move to the end. The options list gains --token and
--api-base, which the CLI already accepts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The skills are shared by every StackGuardian-<org> entry, so removing one
organization's entry with --name no longer removes them from the agents.
remove without --name, and logout --purge, still take the skills out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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