Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ __screenshots__
vite.*.ts.timestamp*
.11ty-vite
.gitlab/scripts/
port

# Vale
config/vale/bin
Expand Down
1 change: 1 addition & 0 deletions config/vale/styles/config/vocabularies/Elements/accept.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ CSS
css
HTML
html
jsDelivr
DOM
dom
Artifactory
Expand Down
868 changes: 510 additions & 358 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ catalog:
markdown-it: 14.2.0
markdown-it-link-attributes: 4.0.1
minisearch: 7.2.0
playwright: 1.59.1
playwright: 1.60.0
postcss: 8.5.15
publint: 0.3.21
react: 19.2.5
Expand Down
21 changes: 18 additions & 3 deletions projects/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ The best way to get started is to run the install script.
curl -fsSL https://nvidia.github.io/elements/install.sh | bash
```

On Windows, run the PowerShell installer.

```powershell
irm https://nvidia.github.io/elements/install.ps1 | iex
```

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.

Alternatively you can install with [Node.js](https://nodejs.org/) and npm.

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

| Skill | Description |
| ----- | ----------- |
| `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. |
| `authoring` | Authoring workflow guidance for creating, editing, or reviewing HTML templates that use nve-* components. |
| `migration` | Migration guidance for moving projects from deprecated Elements APIs to current packages and tools. |
| `about` | Instructions for providing a brief introduction for using the Elements Design System. |
| `authoring` | Best practices and workflow guidance for authoring UI with NVIDIA Elements. |
| `doctor` | Instructions for ensuring the Elements Design System is setup correctly. |
| `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. |
| `integration` | Best practices and workflow guidance for creating or setting up NVIDIA Elements projects. |
| `migration` | Instructions for migrating a project from deprecated Elements APIs using lint tooling and CLI health checks. |
| `search` | Best practices for providing Elements API Documentation. |
| `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. |

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.

### Tools

Expand Down
39 changes: 0 additions & 39 deletions projects/cli/install.cmd

This file was deleted.

39 changes: 39 additions & 0 deletions projects/cli/install.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Elements CLI Installer - Windows PowerShell
# Usage: irm https://NVIDIA.github.io/elements/install.ps1 | iex

$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'

$baseUrl = if ($env:NVE_BASE_URL) { $env:NVE_BASE_URL } else { 'https://NVIDIA.github.io/elements/cli' }
$platformKey = 'windows-x64'
$tempBinary = Join-Path ([System.IO.Path]::GetTempPath()) ("nve-" + [System.IO.Path]::GetRandomFileName() + ".exe")

try {
$manifest = Invoke-RestMethod -Uri "$baseUrl/manifest.json"
$entry = $manifest.platforms.$platformKey

if (-not $entry) {
throw "Platform $platformKey not found in CLI manifest."
}

$runningOnWindows = ($env:OS -eq 'Windows_NT') -or ($IsWindows -eq $true) -or ($PSVersionTable.OS -like '*Windows*')
$downloadName = if ($runningOnWindows -and $entry.filename -notlike '*.exe') { "$($entry.filename).exe" } else { $entry.filename }

Invoke-WebRequest -UseBasicParsing -Uri "$baseUrl/$downloadName" -OutFile $tempBinary
$actualChecksum = (Get-FileHash -Algorithm SHA256 -Path $tempBinary).Hash.ToLowerInvariant()
if ($actualChecksum -ne $entry.checksum) {
throw "Checksum verification failed for $($entry.filename)."
}

& $tempBinary install $tempBinary
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}

Write-Host ''
Write-Host 'Elements CLI installed successfully.'
} finally {
if (Test-Path $tempBinary) {
Remove-Item $tempBinary -Force
}
}
217 changes: 104 additions & 113 deletions projects/cli/install.sh
Original file line number Diff line number Diff line change
@@ -1,142 +1,133 @@
#!/bin/sh
# Elements CLI Installer macOS & Linux
# Elements CLI Installer - macOS and Linux
# Usage: curl -fsSL https://NVIDIA.github.io/elements/install.sh | bash
set -eu

BASE_URL="https://NVIDIA.github.io/elements/cli"
INSTALL_DIR="$HOME/.local/bin"
BIN_NAME="nve"

# --- Colors ---
if [ -t 1 ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' CYAN='' BOLD='' RESET=''
fi
BASE_URL="${NVE_BASE_URL:-https://NVIDIA.github.io/elements/cli}"
TMP_FILE=""

info() { printf "${CYAN}%s${RESET}\n" "$*"; }
warn() { printf "${YELLOW}%s${RESET}\n" "$*"; }
error() { printf "${RED}error: %s${RESET}\n" "$*" >&2; exit 1; }
ok() { printf "${GREEN}%s${RESET}\n" "$*"; }

# --- OS / Arch detection ---
OS="$(uname -s)"
ARCH="$(uname -m)"

case "$OS" in
Darwin)
case "$ARCH" in
arm64) BINARY="nve-macos-arm64" ;;
x86_64) BINARY="nve-macos-x64" ;;
*) error "Unsupported macOS architecture: $ARCH. Supported: arm64, x86_64." ;;
esac
;;
Linux)
case "$ARCH" in
x86_64) BINARY="nve-linux-x64" ;;
aarch64) BINARY="nve-linux-arm64" ;;
*) error "Unsupported Linux architecture: $ARCH. Supported: x86_64, aarch64." ;;
esac
;;
*)
error "Unsupported operating system: $OS. Use install.cmd for Windows."
;;
esac
printf '\033[36mNVIDIA Elements CLI Installer\033[0m\n'

cleanup() {
if [ -n "${TMP_FILE:-}" ]; then
rm -f "$TMP_FILE"
fi
}
trap cleanup EXIT

error() {
printf "error: %s\n" "$*" >&2
exit 1
}

DOWNLOAD_URL="$BASE_URL/$BINARY"
download_file() {
url="$1"
output="${2:-}"

# --- Download helper ---
download() {
if command -v curl >/dev/null 2>&1; then
curl -fsSL "$1"
if [ -n "$output" ]; then
curl -fsSL -o "$output" "$url"
else
curl -fsSL "$url"
fi
elif command -v wget >/dev/null 2>&1; then
wget -qO- "$1"
if [ -n "$output" ]; then
wget -qO "$output" "$url"
else
wget -qO- "$url"
fi
else
error "Neither curl nor wget found. Please install one and try again."
error "Neither curl nor wget found. Install one and try again."
fi
}

# --- Install ---
info "Installing Elements CLI ($BINARY)..."
run_with_spinner() {
message="$1"
success_message="$2"
shift 2

mkdir -p "$INSTALL_DIR"
if [ ! -t 2 ] || [ -n "${CI:-}" ]; then
printf "%s\n" "$message"
"$@"
return $?
fi

info "Downloading..."
download "$DOWNLOAD_URL" > "$INSTALL_DIR/$BIN_NAME"
chmod +x "$INSTALL_DIR/$BIN_NAME"
"$@" &
pid="$!"
frame_index=0

# macOS requires ad-hoc code signature for binaries to execute
if [ "$OS" = "Darwin" ] && command -v codesign >/dev/null 2>&1; then
codesign --sign - --force "$INSTALL_DIR/$BIN_NAME" 2>/dev/null || warn "Ad-hoc code signing failed — binary may not run."
fi
while kill -0 "$pid" 2>/dev/null; do
case "$frame_index" in
0) frame="|" ;;
1) frame="/" ;;
2) frame="-" ;;
*) frame="\\" ;;
esac
printf "\r%s %s" "$frame" "$message" >&2
frame_index=$(((frame_index + 1) % 4))
sleep 0.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Fractional sleep is not POSIX-compliant.

sleep 0.1 requires GNU coreutils or a compatible implementation. On minimal POSIX systems (e.g., BusyBox ash, some BSD variants), this may fail or be ignored. Since this is only for spinner cosmetics and the script targets macOS/Linux where GNU sleep is typical, this is low risk.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@projects/cli/install.sh` at line 68, Replace the non-POSIX fractional sleep
call `sleep 0.1` in projects/cli/install.sh with a portable alternative: either
use an integer-second sleep (e.g., `sleep 1`) for spinner cosmetics, or call a
ubiquitous interpreter to sleep fractional seconds (e.g., `python -c "import
time; time.sleep(0.1)"` or `python3`/`perl` variant) if sub-second timing is
required; update the line containing `sleep 0.1` accordingly and ensure the
chosen interpreter is checked/available before use.

done

set +e
wait "$pid"
status="$?"
set -e

if [ "$status" -eq 0 ]; then
printf "\r\033[K%s\n" "$success_message" >&2
else
printf "\r\033[KFailed. %s\n" "$message" >&2
fi

info "Binary installed to $INSTALL_DIR/$BIN_NAME"
return "$status"
}

# --- PATH setup ---
add_to_path() {
EXPORT_LINE="export PATH=\"$INSTALL_DIR:\$PATH\""
get_manifest_field() {
field="$1"
compact_manifest="$(printf '%s' "$MANIFEST_JSON" | tr -d '\n\r\t ')"
printf '%s' "$compact_manifest" | sed -n "s/.*\"$PLATFORM_KEY\"[^{]*{[^}]*\"$field\":\"\([^\"]*\)\".*/\1/p"
}
Comment thread
coryrylan marked this conversation as resolved.

case "$1" in
*/fish/config.fish)
EXPORT_LINE="fish_add_path $INSTALL_DIR"
;;
esac
get_sha256() {
file="$1"

if [ -f "$1" ] && grep -qF "$INSTALL_DIR" "$1" 2>/dev/null; then
return 0
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$file" | sed 's/ .*//'
elif command -v sha256sum >/dev/null 2>&1; then
sha256sum "$file" | sed 's/ .*//'
else
error "Neither shasum nor sha256sum found. Install one and try again."
fi

printf '\n# Elements CLI\n%s\n' "$EXPORT_LINE" >> "$1"
info "Added $INSTALL_DIR to PATH in $1"
}

IN_PATH=0
case ":${PATH}:" in
*":$INSTALL_DIR:"*) IN_PATH=1 ;;
case "$(uname -s)" in
Darwin) OS="macos" ;;
Linux) OS="linux" ;;
*) error "Unsupported operating system: $(uname -s). Use install.ps1 for Windows." ;;
esac

if [ "$IN_PATH" -eq 0 ]; then
SHELL_NAME="$(basename "$SHELL" 2>/dev/null || echo "sh")"
case "$SHELL_NAME" in
bash)
if [ -f "$HOME/.bashrc" ]; then
add_to_path "$HOME/.bashrc"
elif [ -f "$HOME/.bash_profile" ]; then
add_to_path "$HOME/.bash_profile"
else
add_to_path "$HOME/.bashrc"
fi
;;
zsh)
add_to_path "$HOME/.zshrc"
;;
fish)
mkdir -p "$HOME/.config/fish"
add_to_path "$HOME/.config/fish/config.fish"
;;
*)
warn "Could not detect shell. Add $INSTALL_DIR to your PATH manually."
;;
esac
export PATH="$INSTALL_DIR:$PATH"
fi
case "$(uname -m)" in
arm64 | aarch64) ARCH="arm64" ;;
x86_64 | amd64) ARCH="x64" ;;
*) error "Unsupported architecture: $(uname -m)." ;;
esac

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

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

if [ "$IN_PATH" -eq 0 ]; then
SHELL_RC=".bashrc"
case "$(basename "$SHELL" 2>/dev/null)" in
zsh) SHELL_RC=".zshrc" ;;
fish) SHELL_RC=".config/fish/config.fish" ;;
esac
printf " Restart your shell or run ${CYAN}source ~/%s${RESET} to update PATH.\n" "$SHELL_RC"
TMP_FILE="$(mktemp "${TMPDIR:-/tmp}/nve.XXXXXX")"
run_with_spinner "Downloading Elements CLI..." "Downloaded Elements CLI." download_file "$BASE_URL/$BINARY" "$TMP_FILE"

ACTUAL_CHECKSUM="$(get_sha256 "$TMP_FILE")"
if [ "$ACTUAL_CHECKSUM" != "$CHECKSUM" ]; then
error "Checksum verification failed for $BINARY."
fi
printf "\n"

chmod +x "$TMP_FILE"
"$TMP_FILE" install "$TMP_FILE"
Loading