Skip to content

chore: move installation scripts from docs repo to here#1951

Draft
lc6464 wants to merge 2 commits intosipeed:mainfrom
lc6464:chore/move-scripts
Draft

chore: move installation scripts from docs repo to here#1951
lc6464 wants to merge 2 commits intosipeed:mainfrom
lc6464:chore/move-scripts

Conversation

@lc6464
Copy link
Copy Markdown
Contributor

@lc6464 lc6464 commented Mar 24, 2026

📝 Description

Move installation scripts from docs repo to here.

🔗 Related PR

sipeed/picoclaw_docs#14 (comment)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Moves end-user installation tooling into this repository so releases can be installed without relying on the separate docs repo.

Changes:

  • Added a cross-platform Bash installer for picoclaw releases (user/system mode, GitHub/CDN sources).
  • Added a PowerShell installer covering Windows/Linux/macOS/bsd flows, including PATH updates.
  • Added a MaixCam-focused Python installer/uninstaller for arm64/riscv64 targets.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 11 comments.

File Description
scripts/install/picoclaw/install-picoclaw.sh New Bash-based installer that downloads and installs release artifacts, with user/system layouts.
scripts/install/picoclaw/install-picoclaw.ps1 New PowerShell installer that downloads/extracts artifacts and updates PATH for Windows and Unix-like systems.
scripts/install/maixcam/install_picoclaw.py New Python installer/uninstaller tailored for MaixCam environments (arm64/riscv64).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/install/picoclaw/install-picoclaw.ps1 Outdated
Comment thread scripts/install/maixcam/install_picoclaw.py
Comment on lines +211 to +218
function Invoke-ArtifactDownload {
param(
[Parameter(Mandatory = $true)][string]$Url,
[Parameter(Mandatory = $true)][string]$OutFile
)
Write-Host "Downloading: $Url"
Invoke-WebRequest -Uri $Url -OutFile $OutFile
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Invoke-ArtifactDownload downloads release artifacts but does not perform any integrity verification (checksum/signature). For an installer that will unpack/install executables (potentially as Administrator/root), consider verifying against a published checksums.txt (or signature) from the same release before proceeding.

Copilot uses AI. Check for mistakes.
freebsd) echo "freebsd" ;;
netbsd) echo "netbsd" ;;
mingw*|msys*|cygwin*)
die "Windows shell detected ($u). Please run the PowerShell installer instead: pwsh ./static/scripts/picoclaw/install-picoclaw.ps1 -InstallMode user"
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The Windows-shell error message points to pwsh ./static/scripts/picoclaw/install-picoclaw.ps1 ..., but this repo’s PowerShell installer is located at scripts/install/picoclaw/install-picoclaw.ps1. As written, the guidance will send users to a non-existent path.

Suggested change
die "Windows shell detected ($u). Please run the PowerShell installer instead: pwsh ./static/scripts/picoclaw/install-picoclaw.ps1 -InstallMode user"
die "Windows shell detected ($u). Please run the PowerShell installer instead: pwsh ./scripts/install/picoclaw/install-picoclaw.ps1 -InstallMode user"

Copilot uses AI. Check for mistakes.
fi

if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
printf 'Error: GNU bash 4+ is required. Current version: %s\n' "$BASH_VERSION" >&2
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The installer enforces GNU bash 4+ (BASH_VERSINFO[0] < 4), which will fail on stock macOS (ships bash 3.2) even though this script supports macOS assets. Consider either lowering/removing the version constraint (if no bash-4-only features are used) or updating the UX to instruct macOS users to run with a newer bash (e.g., brew install bash and execute via that binary).

Suggested change
printf 'Error: GNU bash 4+ is required. Current version: %s\n' "$BASH_VERSION" >&2
printf 'Error: GNU bash 4+ is required. Current version: %s\n\n' "$BASH_VERSION" >&2
printf 'On macOS, /bin/bash is often an older 3.x version.\n' >&2
printf 'To install a newer GNU bash using Homebrew:\n' >&2
printf ' brew install bash\n' >&2
printf 'Then re-run this installer explicitly with the new bash, for example:\n' >&2
printf ' /usr/local/bin/bash %s [arguments...]\n' "$0" >&2

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +79
with tarfile.open(tar_file, "r:gz") as tar:
tar.extractall(path=install_dir)

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

tar.extractall() is used on a downloaded archive without validating member paths. A malicious tarball can write files outside /opt/picoclaw via ../ or absolute paths (path traversal). Use a safe extraction routine that validates each member’s resolved path stays within the destination directory before extracting.

Copilot uses AI. Check for mistakes.
Comment on lines +90 to +93
def cleanup_dir(target_dir: Path) -> None:
if target_dir.exists():
shutil.rmtree(target_dir)

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

cleanup_dir() deletes the entire /root/picoclaw directory. Since ensure_picoclaw_dir() uses exist_ok=True, this directory may pre-exist and contain unrelated user data; running the installer would then delete it. Use a unique temporary download directory (e.g., under /tmp), or only delete the specific downloaded file(s) created by this run.

Copilot uses AI. Check for mistakes.
Comment on lines +122 to +132

log "Downloading: $url"
if command_exists curl; then
curl -fsSL "$url" -o "$out"
return
fi
if command_exists wget; then
wget -qO "$out" "$url"
return
fi
die "Neither curl nor wget is available."
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Downloads are performed over HTTPS but without any integrity verification (e.g., validating against checksums.txt from the release). Since this is an installer fetching and executing binaries as the user (or root in system mode), consider downloading the corresponding checksums/signature and verifying before extracting/installing.

Suggested change
log "Downloading: $url"
if command_exists curl; then
curl -fsSL "$url" -o "$out"
return
fi
if command_exists wget; then
wget -qO "$out" "$url"
return
fi
die "Neither curl nor wget is available."
local checksum="${3:-}"
local checksum_type="${4:-sha256}"
log "Downloading: $url"
if command_exists curl; then
curl -fsSL "$url" -o "$out"
elif command_exists wget; then
wget -qO "$out" "$url"
else
die "Neither curl nor wget is available."
fi
# Optional integrity verification: if an expected checksum is provided,
# verify the downloaded file before proceeding.
if [[ -n "$checksum" ]]; then
local actual
case "$checksum_type" in
sha256)
if command_exists sha256sum; then
actual="$(sha256sum "$out" | awk '{print $1}')"
elif command_exists shasum; then
actual="$(shasum -a 256 "$out" | awk '{print $1}')"
else
die "Checksum verification requested, but no sha256sum or shasum found."
fi
;;
*)
die "Unsupported checksum type: $checksum_type"
;;
esac
if [[ "$actual" != "$checksum" ]]; then
die "Checksum verification failed for $out (expected $checksum, got $actual)."
fi
fi

Copilot uses AI. Check for mistakes.
[Parameter(Mandatory = $true)][string]$BinDir
)

$line = 'export PATH="$HOME/.local/bin:$PATH"'
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Set-UnixUserPathExport accepts a BinDir parameter but ignores it and always writes export PATH="$HOME/.local/bin:$PATH". This makes the function misleading and will be wrong if BinDir ever differs from $HOME/.local/bin.

Suggested change
$line = 'export PATH="$HOME/.local/bin:$PATH"'
# Represent BinDir in a portable way for shell rc files:
# - If BinDir is under HomeDir, rewrite the HomeDir prefix as $HOME.
# - Otherwise, use BinDir as-is.
$binPathForExport = $BinDir
if ($BinDir.StartsWith($HomeDir, [StringComparison]::Ordinal)) {
$relative = $BinDir.Substring($HomeDir.Length)
if (-not $relative.StartsWith('/', [StringComparison]::Ordinal)) {
$relative = '/' + $relative
}
$binPathForExport = '$HOME' + $relative
}
# Use a literal $PATH so the target shell expands it, not PowerShell.
$line = "export PATH=""$binPathForExport:`$PATH"""

Copilot uses AI. Check for mistakes.
New-Item -ItemType File -Path $rcPath -Force | Out-Null
}

$hasLine = Select-String -Path $rcPath -Pattern [regex]::Escape($line) -SimpleMatch -Quiet -ErrorAction SilentlyContinue
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Set-UnixUserPathExport uses Select-String -SimpleMatch but also escapes the pattern via [regex]::Escape($line). With -SimpleMatch, the escaped backslashes become literal and the existing line will never match, so the PATH export can be appended repeatedly on every run.

Suggested change
$hasLine = Select-String -Path $rcPath -Pattern [regex]::Escape($line) -SimpleMatch -Quiet -ErrorAction SilentlyContinue
$hasLine = Select-String -Path $rcPath -Pattern [regex]::Escape($line) -Quiet -ErrorAction SilentlyContinue

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings March 24, 2026 07:35
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +153 to +163
try {
Get-ChildItem -Path '/tmp' -Filter 'picoclaw-*' -Directory -ErrorAction SilentlyContinue |
ForEach-Object {
if ($_.FullName -ne $tempInstallRoot) {
Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
} catch {
# Best-effort cleanup; ignore any failures to avoid breaking installation.
}

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This function deletes all /tmp/picoclaw-* directories (except the one it just named). That can remove unrelated user data or other concurrent installs, and it runs even though /tmp is shared across users. Avoid deleting broad globs in /tmp; only remove the directory you created for this run (or use a GUID-based temp dir and rely on OS cleanup).

Suggested change
try {
Get-ChildItem -Path '/tmp' -Filter 'picoclaw-*' -Directory -ErrorAction SilentlyContinue |
ForEach-Object {
if ($_.FullName -ne $tempInstallRoot) {
Remove-Item -LiteralPath $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
}
}
} catch {
# Best-effort cleanup; ignore any failures to avoid breaking installation.
}

Copilot uses AI. Check for mistakes.
return matches[0]


def install_riscv64(tar_file: Path, work_dir: Path) -> None:
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

install_riscv64() takes a work_dir parameter but never uses it. This makes the function signature misleading and can confuse callers/maintainers; either remove the parameter or use it (e.g., as the working directory for downloads/extraction).

Suggested change
def install_riscv64(tar_file: Path, work_dir: Path) -> None:
def install_riscv64(tar_file: Path, work_dir: Path) -> None:
# Ensure the provided work directory exists so it can be used as a staging area if needed.
work_dir.mkdir(parents=True, exist_ok=True)

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +41
def ensure_picoclaw_dir() -> Path:
target_dir = Path("/root/picoclaw")
target_dir.mkdir(parents=True, exist_ok=True)
return target_dir
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This installer writes into /root, /opt, and /usr/bin but doesn't check for root privileges up front. When run without sufficient permissions it will fail mid-way with a less clear exception (e.g., PermissionError). Consider asserting effective UID==0 early (or documenting that it must be run as root) and exiting with a clear message.

Copilot uses AI. Check for mistakes.
New-Item -ItemType File -Path $rcPath -Force | Out-Null
}

$hasLine = Select-String -Path $rcPath -Pattern [regex]::Escape($line) -SimpleMatch -Quiet -ErrorAction SilentlyContinue
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Select-String is invoked with both -SimpleMatch and a regex-escaped pattern. With -SimpleMatch, the backslashes inserted by [regex]::Escape($line) are treated literally, so the check will not match an existing PATH export line and the script will append duplicates on each run. Use either -Pattern $line -SimpleMatch or drop -SimpleMatch and keep the regex pattern.

Suggested change
$hasLine = Select-String -Path $rcPath -Pattern [regex]::Escape($line) -SimpleMatch -Quiet -ErrorAction SilentlyContinue
$hasLine = Select-String -Path $rcPath -Pattern $line -SimpleMatch -Quiet -ErrorAction SilentlyContinue

Copilot uses AI. Check for mistakes.
@sipeed-bot sipeed-bot Bot added type: enhancement New feature or request domain: build labels Mar 24, 2026
@lc6464 lc6464 marked this pull request as draft March 24, 2026 08:00
lc6464 and others added 2 commits March 24, 2026 20:46
@lc6464 lc6464 force-pushed the chore/move-scripts branch from e4da51f to 79dff4a Compare March 24, 2026 12:46
@sipeed-bot
Copy link
Copy Markdown

sipeed-bot Bot commented Apr 17, 2026

@lc6464 Hi! This PR has been inactive for over a week. If there's no update in the next 7 days, it will be closed automatically. If you're still working on it, just leave a comment to keep it open!

@lc6464
Copy link
Copy Markdown
Contributor Author

lc6464 commented Apr 17, 2026

👀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants