Skip to content

Commit 0379d0e

Browse files
committed
feat(cli): improve installer script
- Refactors installer logic out of sh file and into testable cli installer command - Added a new `install.ps1` script for Windows installations using PowerShell. - Updated `install.sh` for improved error handling and user feedback. - Modified `package.json` to reflect new installation commands and paths. - Enhanced README with instructions for the new PowerShell installer. - Updated tests to ensure compatibility with the new installation process. Signed-off-by: Cory Rylan <crylan@nvidia.com>
1 parent 59d8349 commit 0379d0e

44 files changed

Lines changed: 2842 additions & 608 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ __screenshots__
2323
vite.*.ts.timestamp*
2424
.11ty-vite
2525
.gitlab/scripts/
26+
port
2627

2728
# Vale
2829
config/vale/bin

‎config/vale/styles/config/vocabularies/Elements/accept.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ CSS
3939
css
4040
HTML
4141
html
42+
jsDelivr
4243
DOM
4344
dom
4445
Artifactory

‎pnpm-lock.yaml‎

Lines changed: 510 additions & 358 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pnpm-workspace.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ catalog:
100100
markdown-it: 14.2.0
101101
markdown-it-link-attributes: 4.0.1
102102
minisearch: 7.2.0
103-
playwright: 1.59.1
103+
playwright: 1.60.0
104104
postcss: 8.5.15
105105
publint: 0.3.21
106106
react: 19.2.5

‎projects/cli/README.md‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ The best way to get started is to run the install script.
3030
curl -fsSL https://nvidia.github.io/elements/install.sh | bash
3131
```
3232

33+
On Windows, run the PowerShell installer.
34+
35+
```powershell
36+
irm https://nvidia.github.io/elements/install.ps1 | iex
37+
```
38+
39+
For agents and CI, invoke the canonical path directly: `$HOME/.nve/bin/nve` on macOS and Linux, or `$env:LOCALAPPDATA\nve\bin\nve.exe` on Windows.
40+
3341
Alternatively you can install with [Node.js](https://nodejs.org/) and npm.
3442

3543
```shell
@@ -142,9 +150,16 @@ Skills provide persistent context to AI agents for building UI with Elements.
142150

143151
| Skill | Description |
144152
| ----- | ----------- |
145-
| `elements` | Build UI with NVIDIA Elements (NVE). Provides authoring guidelines, workflow steps, and API best practices for creating, editing, or reviewing HTML templates that use nve-* components. |
146-
| `authoring` | Authoring workflow guidance for creating, editing, or reviewing HTML templates that use nve-* components. |
147-
| `migration` | Migration guidance for moving projects from deprecated Elements APIs to current packages and tools. |
153+
| `about` | Instructions for providing a brief introduction for using the Elements Design System. |
154+
| `authoring` | Best practices and workflow guidance for authoring UI with NVIDIA Elements. |
155+
| `doctor` | Instructions for ensuring the Elements Design System is setup correctly. |
156+
| `artifact` | Use when creating throwaway UI artifacts, prototypes, demos, Claude Artifacts, Codex, or GPT Sites pages, or other standalone HTML interfaces that should use the NVIDIA Elements CDN template. |
157+
| `integration` | Best practices and workflow guidance for creating or setting up NVIDIA Elements projects. |
158+
| `migration` | Instructions for migrating a project from deprecated Elements APIs using lint tooling and CLI health checks. |
159+
| `search` | Best practices for providing Elements API Documentation. |
160+
| `elements` | Default skill for UI-related work or NVIDIA Elements (`nve-*`), including HTML, CSS, layout, theming, components, applications, prototypes, Claude Artifacts, Codex Sites pages, and standalone UI artifacts. |
161+
162+
Run `nve skills.list` or call MCP `skills_list` for the authoritative list. Deployments with the playground service enabled can also expose a `playground` skill for creating Elements Playground prototypes.
148163

149164
### Tools
150165

‎projects/cli/install.cmd‎

Lines changed: 0 additions & 39 deletions
This file was deleted.

‎projects/cli/install.ps1‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Elements CLI Installer - Windows PowerShell
2+
# Usage: irm https://NVIDIA.github.io/elements/install.ps1 | iex
3+
4+
$ErrorActionPreference = 'Stop'
5+
$ProgressPreference = 'SilentlyContinue'
6+
7+
$baseUrl = if ($env:NVE_BASE_URL) { $env:NVE_BASE_URL } else { 'https://NVIDIA.github.io/elements/cli' }
8+
$platformKey = 'windows-x64'
9+
$tempBinary = Join-Path ([System.IO.Path]::GetTempPath()) ("nve-" + [System.IO.Path]::GetRandomFileName() + ".exe")
10+
11+
try {
12+
$manifest = Invoke-RestMethod -Uri "$baseUrl/manifest.json"
13+
$entry = $manifest.platforms.$platformKey
14+
15+
if (-not $entry) {
16+
throw "Platform $platformKey not found in CLI manifest."
17+
}
18+
19+
$runningOnWindows = ($env:OS -eq 'Windows_NT') -or ($IsWindows -eq $true) -or ($PSVersionTable.OS -like '*Windows*')
20+
$downloadName = if ($runningOnWindows -and $entry.filename -notlike '*.exe') { "$($entry.filename).exe" } else { $entry.filename }
21+
22+
Invoke-WebRequest -UseBasicParsing -Uri "$baseUrl/$downloadName" -OutFile $tempBinary
23+
$actualChecksum = (Get-FileHash -Algorithm SHA256 -Path $tempBinary).Hash.ToLowerInvariant()
24+
if ($actualChecksum -ne $entry.checksum) {
25+
throw "Checksum verification failed for $($entry.filename)."
26+
}
27+
28+
& $tempBinary install $tempBinary
29+
if ($LASTEXITCODE -ne 0) {
30+
exit $LASTEXITCODE
31+
}
32+
33+
Write-Host ''
34+
Write-Host 'Elements CLI installed successfully.'
35+
} finally {
36+
if (Test-Path $tempBinary) {
37+
Remove-Item $tempBinary -Force
38+
}
39+
}

‎projects/cli/install.sh‎

Lines changed: 104 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,133 @@
11
#!/bin/sh
2-
# Elements CLI Installer macOS & Linux
2+
# Elements CLI Installer - macOS and Linux
33
# Usage: curl -fsSL https://NVIDIA.github.io/elements/install.sh | bash
44
set -eu
55

6-
BASE_URL="https://NVIDIA.github.io/elements/cli"
7-
INSTALL_DIR="$HOME/.local/bin"
8-
BIN_NAME="nve"
9-
10-
# --- Colors ---
11-
if [ -t 1 ]; then
12-
RED='\033[0;31m'
13-
GREEN='\033[0;32m'
14-
YELLOW='\033[0;33m'
15-
CYAN='\033[0;36m'
16-
BOLD='\033[1m'
17-
RESET='\033[0m'
18-
else
19-
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
20-
fi
6+
BASE_URL="${NVE_BASE_URL:-https://NVIDIA.github.io/elements/cli}"
7+
TMP_FILE=""
218

22-
info() { printf "${CYAN}%s${RESET}\n" "$*"; }
23-
warn() { printf "${YELLOW}%s${RESET}\n" "$*"; }
24-
error() { printf "${RED}error: %s${RESET}\n" "$*" >&2; exit 1; }
25-
ok() { printf "${GREEN}%s${RESET}\n" "$*"; }
26-
27-
# --- OS / Arch detection ---
28-
OS="$(uname -s)"
29-
ARCH="$(uname -m)"
30-
31-
case "$OS" in
32-
Darwin)
33-
case "$ARCH" in
34-
arm64) BINARY="nve-macos-arm64" ;;
35-
x86_64) BINARY="nve-macos-x64" ;;
36-
*) error "Unsupported macOS architecture: $ARCH. Supported: arm64, x86_64." ;;
37-
esac
38-
;;
39-
Linux)
40-
case "$ARCH" in
41-
x86_64) BINARY="nve-linux-x64" ;;
42-
aarch64) BINARY="nve-linux-arm64" ;;
43-
*) error "Unsupported Linux architecture: $ARCH. Supported: x86_64, aarch64." ;;
44-
esac
45-
;;
46-
*)
47-
error "Unsupported operating system: $OS. Use install.cmd for Windows."
48-
;;
49-
esac
9+
printf '\033[36mNVIDIA Elements CLI Installer\033[0m\n'
10+
11+
cleanup() {
12+
if [ -n "${TMP_FILE:-}" ]; then
13+
rm -f "$TMP_FILE"
14+
fi
15+
}
16+
trap cleanup EXIT
17+
18+
error() {
19+
printf "error: %s\n" "$*" >&2
20+
exit 1
21+
}
5022

51-
DOWNLOAD_URL="$BASE_URL/$BINARY"
23+
download_file() {
24+
url="$1"
25+
output="${2:-}"
5226

53-
# --- Download helper ---
54-
download() {
5527
if command -v curl >/dev/null 2>&1; then
56-
curl -fsSL "$1"
28+
if [ -n "$output" ]; then
29+
curl -fsSL -o "$output" "$url"
30+
else
31+
curl -fsSL "$url"
32+
fi
5733
elif command -v wget >/dev/null 2>&1; then
58-
wget -qO- "$1"
34+
if [ -n "$output" ]; then
35+
wget -qO "$output" "$url"
36+
else
37+
wget -qO- "$url"
38+
fi
5939
else
60-
error "Neither curl nor wget found. Please install one and try again."
40+
error "Neither curl nor wget found. Install one and try again."
6141
fi
6242
}
6343

64-
# --- Install ---
65-
info "Installing Elements CLI ($BINARY)..."
44+
run_with_spinner() {
45+
message="$1"
46+
success_message="$2"
47+
shift 2
6648

67-
mkdir -p "$INSTALL_DIR"
49+
if [ ! -t 2 ] || [ -n "${CI:-}" ]; then
50+
printf "%s\n" "$message"
51+
"$@"
52+
return $?
53+
fi
6854

69-
info "Downloading..."
70-
download "$DOWNLOAD_URL" > "$INSTALL_DIR/$BIN_NAME"
71-
chmod +x "$INSTALL_DIR/$BIN_NAME"
55+
"$@" &
56+
pid="$!"
57+
frame_index=0
7258

73-
# macOS requires ad-hoc code signature for binaries to execute
74-
if [ "$OS" = "Darwin" ] && command -v codesign >/dev/null 2>&1; then
75-
codesign --sign - --force "$INSTALL_DIR/$BIN_NAME" 2>/dev/null || warn "Ad-hoc code signing failed — binary may not run."
76-
fi
59+
while kill -0 "$pid" 2>/dev/null; do
60+
case "$frame_index" in
61+
0) frame="|" ;;
62+
1) frame="/" ;;
63+
2) frame="-" ;;
64+
*) frame="\\" ;;
65+
esac
66+
printf "\r%s %s" "$frame" "$message" >&2
67+
frame_index=$(((frame_index + 1) % 4))
68+
sleep 0.1
69+
done
70+
71+
set +e
72+
wait "$pid"
73+
status="$?"
74+
set -e
75+
76+
if [ "$status" -eq 0 ]; then
77+
printf "\r\033[K%s\n" "$success_message" >&2
78+
else
79+
printf "\r\033[KFailed. %s\n" "$message" >&2
80+
fi
7781

78-
info "Binary installed to $INSTALL_DIR/$BIN_NAME"
82+
return "$status"
83+
}
7984

80-
# --- PATH setup ---
81-
add_to_path() {
82-
EXPORT_LINE="export PATH=\"$INSTALL_DIR:\$PATH\""
85+
get_manifest_field() {
86+
field="$1"
87+
compact_manifest="$(printf '%s' "$MANIFEST_JSON" | tr -d '\n\r\t ')"
88+
printf '%s' "$compact_manifest" | sed -n "s/.*\"$PLATFORM_KEY\"[^{]*{[^}]*\"$field\":\"\([^\"]*\)\".*/\1/p"
89+
}
8390

84-
case "$1" in
85-
*/fish/config.fish)
86-
EXPORT_LINE="fish_add_path $INSTALL_DIR"
87-
;;
88-
esac
91+
get_sha256() {
92+
file="$1"
8993

90-
if [ -f "$1" ] && grep -qF "$INSTALL_DIR" "$1" 2>/dev/null; then
91-
return 0
94+
if command -v shasum >/dev/null 2>&1; then
95+
shasum -a 256 "$file" | sed 's/ .*//'
96+
elif command -v sha256sum >/dev/null 2>&1; then
97+
sha256sum "$file" | sed 's/ .*//'
98+
else
99+
error "Neither shasum nor sha256sum found. Install one and try again."
92100
fi
93-
94-
printf '\n# Elements CLI\n%s\n' "$EXPORT_LINE" >> "$1"
95-
info "Added $INSTALL_DIR to PATH in $1"
96101
}
97102

98-
IN_PATH=0
99-
case ":${PATH}:" in
100-
*":$INSTALL_DIR:"*) IN_PATH=1 ;;
103+
case "$(uname -s)" in
104+
Darwin) OS="macos" ;;
105+
Linux) OS="linux" ;;
106+
*) error "Unsupported operating system: $(uname -s). Use install.ps1 for Windows." ;;
101107
esac
102108

103-
if [ "$IN_PATH" -eq 0 ]; then
104-
SHELL_NAME="$(basename "$SHELL" 2>/dev/null || echo "sh")"
105-
case "$SHELL_NAME" in
106-
bash)
107-
if [ -f "$HOME/.bashrc" ]; then
108-
add_to_path "$HOME/.bashrc"
109-
elif [ -f "$HOME/.bash_profile" ]; then
110-
add_to_path "$HOME/.bash_profile"
111-
else
112-
add_to_path "$HOME/.bashrc"
113-
fi
114-
;;
115-
zsh)
116-
add_to_path "$HOME/.zshrc"
117-
;;
118-
fish)
119-
mkdir -p "$HOME/.config/fish"
120-
add_to_path "$HOME/.config/fish/config.fish"
121-
;;
122-
*)
123-
warn "Could not detect shell. Add $INSTALL_DIR to your PATH manually."
124-
;;
125-
esac
126-
export PATH="$INSTALL_DIR:$PATH"
127-
fi
109+
case "$(uname -m)" in
110+
arm64 | aarch64) ARCH="arm64" ;;
111+
x86_64 | amd64) ARCH="x64" ;;
112+
*) error "Unsupported architecture: $(uname -m)." ;;
113+
esac
128114

129-
# --- Verify ---
130-
printf "${GREEN}${BOLD}Elements CLI installed successfully!${RESET}\n"
115+
PLATFORM_KEY="$OS-$ARCH"
116+
MANIFEST_JSON="$(download_file "$BASE_URL/manifest.json")"
117+
BINARY="$(get_manifest_field "filename")"
118+
CHECKSUM="$(get_manifest_field "checksum")"
131119

132-
printf "\n Run ${CYAN}nve${RESET} to get started.\n"
120+
if [ -z "$BINARY" ] || [ -z "$CHECKSUM" ]; then
121+
error "Platform $PLATFORM_KEY not found in CLI manifest."
122+
fi
133123

134-
if [ "$IN_PATH" -eq 0 ]; then
135-
SHELL_RC=".bashrc"
136-
case "$(basename "$SHELL" 2>/dev/null)" in
137-
zsh) SHELL_RC=".zshrc" ;;
138-
fish) SHELL_RC=".config/fish/config.fish" ;;
139-
esac
140-
printf " Restart your shell or run ${CYAN}source ~/%s${RESET} to update PATH.\n" "$SHELL_RC"
124+
TMP_FILE="$(mktemp "${TMPDIR:-/tmp}/nve.XXXXXX")"
125+
run_with_spinner "Downloading Elements CLI..." "Downloaded Elements CLI." download_file "$BASE_URL/$BINARY" "$TMP_FILE"
126+
127+
ACTUAL_CHECKSUM="$(get_sha256 "$TMP_FILE")"
128+
if [ "$ACTUAL_CHECKSUM" != "$CHECKSUM" ]; then
129+
error "Checksum verification failed for $BINARY."
141130
fi
142-
printf "\n"
131+
132+
chmod +x "$TMP_FILE"
133+
"$TMP_FILE" install "$TMP_FILE"

0 commit comments

Comments
 (0)