Skip to content

Commit 619a058

Browse files
authored
fix(install): use gh CLI for release downloads instead of HTTP (#285)
1 parent 887f050 commit 619a058

File tree

3 files changed

+89
-79
lines changed

3 files changed

+89
-79
lines changed

.github/workflows/publish.yml

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,6 @@ jobs:
369369
path: release/
370370
merge-multiple: true
371371

372-
- name: Stage install script
373-
run: cp install.sh release/install.sh
374-
375372
- name: Generate checksums
376373
run: |
377374
set -euo pipefail
@@ -389,49 +386,42 @@ jobs:
389386
- name: Create / update GitHub Release
390387
uses: softprops/action-gh-release@v2
391388
with:
392-
name: OpenShell Latest Devel
389+
name: OpenShell Development Build
393390
prerelease: true
394391
tag_name: devel
395392
target_commitish: ${{ github.sha }}
396393
body: |
397-
This devel build is automatically built on every commit to main that passes CI.
394+
This build is automatically built on every commit to main that passes CI.
398395
399396
> **NOTE**: This is a development build, not a tagged release, and may be unstable.
400397
401398
### Quick install
402399
400+
Requires the [GitHub CLI (`gh`)](https://cli.github.com) to be installed and authenticated.
401+
403402
```bash
404-
curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/install.sh | sh
403+
sh -c 'ARCH=$(uname -m); OS=$(uname -s); \
404+
case "${OS}-${ARCH}" in \
405+
Linux-x86_64) ASSET="openshell-x86_64-unknown-linux-musl.tar.gz" ;; \
406+
Linux-aarch64) ASSET="openshell-aarch64-unknown-linux-musl.tar.gz" ;; \
407+
Darwin-arm64) ASSET="openshell-aarch64-apple-darwin.tar.gz" ;; \
408+
*) echo "Unsupported platform: ${OS}-${ARCH}" >&2; exit 1 ;; \
409+
esac; \
410+
gh release download devel --repo NVIDIA/OpenShell --pattern "${ASSET}" -O - \
411+
| tar xz \
412+
&& sudo install -m 755 openshell /usr/local/bin/openshell'
405413
```
406414
407415
### Assets
408416
409417
| File | Platform | Install |
410418
|------|----------|---------|
411-
| `openshell-x86_64-unknown-linux-musl.tar.gz` | Linux x86_64 | `curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-x86_64-unknown-linux-musl.tar.gz \| tar xz && sudo mv openshell /usr/local/bin/` |
412-
| `openshell-aarch64-unknown-linux-musl.tar.gz` | Linux aarch64 / ARM64 | `curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-aarch64-unknown-linux-musl.tar.gz \| tar xz && sudo mv openshell /usr/local/bin/` |
413-
| `openshell-aarch64-apple-darwin.tar.gz` | macOS Apple Silicon | `curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-aarch64-apple-darwin.tar.gz \| tar xz && sudo mv openshell /usr/local/bin/` |
414-
| `install.sh` | All platforms | `curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/install.sh \| sh` |
419+
| `openshell-x86_64-unknown-linux-musl.tar.gz` | Linux x86_64 | `gh release download devel --repo NVIDIA/OpenShell --pattern "openshell-x86_64-unknown-linux-musl.tar.gz" -O - \| tar xz && sudo install -m 755 openshell /usr/local/bin/openshell` |
420+
| `openshell-aarch64-unknown-linux-musl.tar.gz` | Linux aarch64 / ARM64 | `gh release download devel --repo NVIDIA/OpenShell --pattern "openshell-aarch64-unknown-linux-musl.tar.gz" -O - \| tar xz && sudo install -m 755 openshell /usr/local/bin/openshell` |
421+
| `openshell-aarch64-apple-darwin.tar.gz` | macOS Apple Silicon | `gh release download devel --repo NVIDIA/OpenShell --pattern "openshell-aarch64-apple-darwin.tar.gz" -O - \| tar xz && sudo install -m 755 openshell /usr/local/bin/openshell` |
415422
| `openshell-checksums-sha256.txt` | — | SHA256 checksums for all archives |
416-
417-
### Manual install
418-
419-
```bash
420-
# Linux x86_64
421-
curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-x86_64-unknown-linux-musl.tar.gz | tar xz
422-
sudo mv openshell /usr/local/bin/
423-
424-
# Linux aarch64
425-
curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-aarch64-unknown-linux-musl.tar.gz | tar xz
426-
sudo mv openshell /usr/local/bin/
427-
428-
# macOS (Apple Silicon)
429-
curl -fsSL https://github.com/NVIDIA/OpenShell/releases/download/devel/openshell-aarch64-apple-darwin.tar.gz | tar xz
430-
sudo mv openshell /usr/local/bin/
431-
```
432423
files: |
433424
release/openshell-x86_64-unknown-linux-musl.tar.gz
434425
release/openshell-aarch64-unknown-linux-musl.tar.gz
435426
release/openshell-aarch64-apple-darwin.tar.gz
436427
release/openshell-checksums-sha256.txt
437-
release/install.sh

README.md

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,26 @@ Want to run on cloud compute? [Launch on Brev](https://brev.nvidia.com/launchabl
1515

1616
### Install
1717

18-
**Binary (recommended):**
18+
**Binary (recommended — requires [GitHub CLI](https://cli.github.com)):**
1919

2020
```bash
21-
curl -fsSL https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
21+
sh -c 'ARCH=$(uname -m); OS=$(uname -s); \
22+
case "${OS}-${ARCH}" in \
23+
Linux-x86_64) ASSET="openshell-x86_64-unknown-linux-musl.tar.gz" ;; \
24+
Linux-aarch64) ASSET="openshell-aarch64-unknown-linux-musl.tar.gz" ;; \
25+
Darwin-arm64) ASSET="openshell-aarch64-apple-darwin.tar.gz" ;; \
26+
*) echo "Unsupported platform: ${OS}-${ARCH}" >&2; exit 1 ;; \
27+
esac; \
28+
gh release download devel --repo NVIDIA/OpenShell --pattern "${ASSET}" -O - \
29+
| tar xz \
30+
&& sudo install -m 755 openshell /usr/local/bin/openshell'
2231
```
2332

24-
The install script auto-detects your platform (Linux x86_64, Linux aarch64, macOS Apple Silicon) and places the `openshell` binary in `/usr/local/bin`. See the [releases page](https://github.com/NVIDIA/OpenShell/releases) for manual download options.
33+
Or use the install script from the repository:
34+
35+
```bash
36+
./install.sh
37+
```
2538

2639
**From PyPI (requires [uv](https://docs.astral.sh/uv/)):**
2740

@@ -84,20 +97,20 @@ OpenShell applies defense in depth across four policy domains:
8497
| Layer | What it protects | When it applies |
8598
| ---------- | --------------------------------------------------- | --------------------------- |
8699
| Filesystem | Prevents reads/writes outside allowed paths. | Locked at sandbox creation. |
87-
| Network | Blocks unauthorized outbound connections. | Hot-reloadable at runtime. |
88-
| Process | Blocks privilege escalation and dangerous syscalls. | Locked at sandbox creation. |
89-
| Inference | Reroutes model API calls to controlled backends. | Hot-reloadable at runtime. |
100+
| Network | Blocks unauthorized outbound connections. | Hot-reloadable at runtime. |
101+
| Process | Blocks privilege escalation and dangerous syscalls. | Locked at sandbox creation. |
102+
| Inference | Reroutes model API calls to controlled backends. | Hot-reloadable at runtime. |
90103

91104
Policies are declarative YAML files. Static sections (filesystem, process) are locked at creation; dynamic sections (network, inference) can be hot-reloaded on a running sandbox with `openshell policy set`.
92105

93106
## Supported Agents
94107

95-
| Agent | Source | Notes |
96-
|---|---|---|
97-
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | Built-in | Works out of the box. Requires `ANTHROPIC_API_KEY`. |
98-
| [OpenCode](https://opencode.ai/) | Built-in | Works out of the box. Requires `OPENAI_API_KEY` or `OPENROUTER_API_KEY`. |
99-
| [Codex](https://developers.openai.com/codex) | Built-in | Works out of the box. Requires `OPENAI_API_KEY`. |
100-
| [OpenClaw](https://openclaw.ai/) | [Community](https://github.com/NVIDIA/OpenShell-Community) | Launch with `openshell sandbox create --from openclaw`. |
108+
| Agent | Source | Notes |
109+
| ------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ |
110+
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | Built-in | Works out of the box. Requires `ANTHROPIC_API_KEY`. |
111+
| [OpenCode](https://opencode.ai/) | Built-in | Works out of the box. Requires `OPENAI_API_KEY` or `OPENROUTER_API_KEY`. |
112+
| [Codex](https://developers.openai.com/codex) | Built-in | Works out of the box. Requires `OPENAI_API_KEY`. |
113+
| [OpenClaw](https://openclaw.ai/) | [Community](https://github.com/NVIDIA/OpenShell-Community) | Launch with `openshell sandbox create --from openclaw`. |
101114

102115
## How It Works
103116

@@ -109,27 +122,27 @@ OpenShell isolates each sandbox in its own container with policy-enforced egress
109122

110123
Under the hood, the gateway runs as a [K3s](https://k3s.io/) Kubernetes cluster inside Docker — no separate K8s install required.
111124

112-
| Component | Role |
113-
|---|---|
114-
| **Gateway** | Control-plane API that coordinates sandbox lifecycle and acts as the auth boundary. |
115-
| **Sandbox** | Isolated runtime with container supervision and policy-enforced egress routing. |
116-
| **Policy Engine** | Enforces filesystem, network, and process constraints from application layer down to kernel. |
117-
| **Privacy Router** | Privacy-aware LLM routing that keeps sensitive context on sandbox compute. |
125+
| Component | Role |
126+
| ------------------ | -------------------------------------------------------------------------------------------- |
127+
| **Gateway** | Control-plane API that coordinates sandbox lifecycle and acts as the auth boundary. |
128+
| **Sandbox** | Isolated runtime with container supervision and policy-enforced egress routing. |
129+
| **Policy Engine** | Enforces filesystem, network, and process constraints from application layer down to kernel. |
130+
| **Privacy Router** | Privacy-aware LLM routing that keeps sensitive context on sandbox compute. |
118131

119132
## Key Commands
120133

121-
| Command | Description |
122-
|---|---|
123-
| `openshell sandbox create -- <agent>` | Create a sandbox and launch an agent. |
124-
| `openshell sandbox connect [name]` | SSH into a running sandbox. |
125-
| `openshell sandbox list` | List all sandboxes. |
126-
| `openshell sandbox delete <name>` | Delete a sandbox. |
127-
| `openshell provider create --type claude --from-existing` | Create a credential provider from env vars. |
128-
| `openshell policy set <name> --policy file.yaml` | Apply or update a policy on a running sandbox. |
129-
| `openshell policy get <name>` | Show the active policy. |
130-
| `openshell inference set --provider <p> --model <m>` | Configure the `inference.local` endpoint. |
131-
| `openshell logs [name] --tail` | Stream sandbox logs. |
132-
| `openshell term` | Launch the real-time terminal UI for debugging. |
134+
| Command | Description |
135+
| --------------------------------------------------------- | ----------------------------------------------- |
136+
| `openshell sandbox create -- <agent>` | Create a sandbox and launch an agent. |
137+
| `openshell sandbox connect [name]` | SSH into a running sandbox. |
138+
| `openshell sandbox list` | List all sandboxes. |
139+
| `openshell sandbox delete <name>` | Delete a sandbox. |
140+
| `openshell provider create --type claude --from-existing` | Create a credential provider from env vars. |
141+
| `openshell policy set <name> --policy file.yaml` | Apply or update a policy on a running sandbox. |
142+
| `openshell policy get <name>` | Show the active policy. |
143+
| `openshell inference set --provider <p> --model <m>` | Configure the `inference.local` endpoint. |
144+
| `openshell logs [name] --tail` | Stream sandbox logs. |
145+
| `openshell term` | Launch the real-time terminal UI for debugging. |
133146

134147
See the full [CLI reference](https://github.com/NVIDIA/OpenShell/blob/main/docs/reference/cli.md) for all commands, flags, and environment variables.
135148

install.sh

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
#
55
# Install the OpenShell CLI binary.
66
#
7+
# Requires the GitHub CLI (gh) to be installed and authenticated, since this
8+
# repository is internal and public HTTP download links are not available.
9+
#
710
# Usage:
8-
# curl -fsSL https://raw.githubusercontent.com/NVIDIA/OpenShell/main/install.sh | sh
11+
# ./install.sh
912
#
1013
# Environment variables:
1114
# OPENSHELL_VERSION - Release tag to install (default: "devel")
@@ -57,43 +60,47 @@ get_target() {
5760
echo "$target"
5861
}
5962

60-
download() {
61-
url="$1" dest="$2"
62-
if command -v curl >/dev/null 2>&1; then
63-
curl -fsSL -o "$dest" "$url"
64-
elif command -v wget >/dev/null 2>&1; then
65-
wget -qO "$dest" "$url"
66-
else
67-
error "curl or wget is required"
68-
fi
69-
}
70-
7163
verify_checksum() {
7264
archive="$1" checksums="$2" filename="$3"
65+
expected="$(grep "$filename" "$checksums" | awk '{print $1}')"
7366

74-
if command -v sha256sum >/dev/null 2>&1; then
75-
echo "$(grep "$filename" "$checksums" | awk '{print $1}') $archive" | sha256sum -c --quiet 2>/dev/null
76-
elif command -v shasum >/dev/null 2>&1; then
77-
echo "$(grep "$filename" "$checksums" | awk '{print $1}') $archive" | shasum -a 256 -c --quiet 2>/dev/null
67+
if [ -z "$expected" ]; then
68+
info "warning: no checksum found for $filename, skipping verification"
69+
return 0
70+
fi
71+
72+
# Prefer shasum (ships with macOS and most Linux); the macOS /sbin/sha256sum
73+
# does not support -c / stdin check mode.
74+
if command -v shasum >/dev/null 2>&1; then
75+
echo "$expected $archive" | shasum -a 256 -c --quiet 2>/dev/null
76+
elif command -v sha256sum >/dev/null 2>&1; then
77+
echo "$expected $archive" | sha256sum -c --quiet 2>/dev/null
7878
else
7979
info "warning: sha256sum/shasum not found, skipping checksum verification"
8080
return 0
8181
fi
8282
}
8383

8484
main() {
85+
command -v gh >/dev/null 2>&1 || error "the GitHub CLI (gh) is required; install it from https://cli.github.com"
86+
8587
target="$(get_target)"
8688
filename="openshell-${target}.tar.gz"
87-
base_url="https://github.com/${REPO}/releases/download/${VERSION}"
8889

8990
tmpdir="$(mktemp -d)"
9091
trap 'rm -rf "$tmpdir"' EXIT
9192

9293
info "downloading ${filename} (${VERSION})..."
93-
download "${base_url}/${filename}" "${tmpdir}/${filename}"
94+
gh release download "${VERSION}" \
95+
--repo "${REPO}" \
96+
--pattern "${filename}" \
97+
--output "${tmpdir}/${filename}"
9498

9599
info "verifying checksum..."
96-
download "${base_url}/openshell-checksums-sha256.txt" "${tmpdir}/checksums.txt"
100+
gh release download "${VERSION}" \
101+
--repo "${REPO}" \
102+
--pattern "openshell-checksums-sha256.txt" \
103+
--output "${tmpdir}/checksums.txt"
97104
if ! verify_checksum "${tmpdir}/${filename}" "${tmpdir}/checksums.txt" "$filename"; then
98105
error "checksum verification failed"
99106
fi
@@ -103,11 +110,11 @@ main() {
103110

104111
info "installing to ${INSTALL_DIR}/openshell..."
105112
if [ -w "$INSTALL_DIR" ]; then
106-
mv "${tmpdir}/openshell" "${INSTALL_DIR}/openshell"
113+
install -m 755 "${tmpdir}/openshell" "${INSTALL_DIR}/openshell"
107114
else
108-
sudo mv "${tmpdir}/openshell" "${INSTALL_DIR}/openshell"
115+
info "sudo access is required to install to ${INSTALL_DIR}"
116+
sudo install -m 755 "${tmpdir}/openshell" "${INSTALL_DIR}/openshell"
109117
fi
110-
chmod +x "${INSTALL_DIR}/openshell"
111118

112119
info "installed openshell $(${INSTALL_DIR}/openshell --version 2>/dev/null || echo "${VERSION}") to ${INSTALL_DIR}/openshell"
113120
}

0 commit comments

Comments
 (0)