Jesús Pérez 2f6089caaf # Summary
feat: bootstrap installer with robust archive extraction, version mismatch handling, and improved PATH messaging

## Detailed Description

This commit implements a production-ready bootstrap installer with comprehensive error handling, version-agnostic archive extraction, and clear user messaging. All improvements follow DRY principles using symlink-based architecture for single-source-of-truth maintenance.

## Major Changes (Session 2025-10-19)

### 0. Bootstrap Installer & Distribution Improvements (NEW)

#### 0a. Install Script Architecture - DRY Design

**Issue**: Code duplication across installation paths
- `./install.sh`, `./scripts/templates/install.sh`, `installers/bootstrap/install.sh` were separate copies
- Changes required updating multiple files
- Risk of divergence and inconsistency

**Solution**: Implemented symlink-based DRY architecture
- Single source of truth: `installers/bootstrap/install.sh` (1,247 lines)
- Symlinks created:
  - `./install.sh` → `installers/bootstrap/install.sh`
  - `./scripts/templates/install.sh` → `installers/bootstrap/install.sh`
- All changes automatically propagate through symlinks
- No code duplication

**Impact**:
-  Single maintenance point for all install scripts
-  Consistent behavior across all paths
-  Reduced maintenance burden
-  No divergence risk

#### 0b. Archive Extraction - Version-Agnostic Binary Detection

**Issue**: "No Nushell binary found in extracted archive"
- Script failed when extracting from `nushell-full-0.108.0-darwin-arm64.tar.gz`
- Error occurred even though binaries were present at `nushell-full-0.108.0/bin/nu`

**Root Cause**: `find` command returning parent directory itself in results
```bash
#  OLD - find returns parent directory first
local extracted=$(find "$extract_dir" -maxdepth 1 -type d -name "nushell-*" | head -1)
# Returns: /tmp/nushell-install-22919/nushell-extract (parent!)
# Should return: /tmp/nushell-install-22919/nushell-extract/nushell-full-0.108.0 (subdirectory)
```

**Solution**: Added `-not -path` to exclude starting directory
```bash
#  NEW - exclude parent directory
local extracted=$(find "$extract_dir" -maxdepth 1 -type d -name "nushell-*" -not -path "$extract_dir" | head -1)
# Now correctly returns the subdirectory
```

**Additional Improvements**:
- 4-level fallback detection strategy:
  1. Check `$extracted/bin/nu` (subdirectory structure)
  2. Check `$extracted/nu` (flat structure)
  3. Fallback search for any `nushell-*` subdirectory with `bin/nu`
  4. Last resort recursive search for any executable named `nu`
- Validates binaries exist before using them
- Clear error reporting with all search locations

**Version-Agnostic**:
- Uses `nushell-*` pattern (not hardcoded version numbers)
- Works with any Nushell version: 0.107, 0.108, 0.109, etc.
- Supports both `.tar.gz` and `.zip` archive formats

**Impact**:
-  Archive extraction works reliably
-  Works with any Nushell version
-  Clear error messages guide users
-  Multiple archive structure support

#### 0c. Plugin Registration - Version Mismatch Handling

**Issue**: Plugin registration failed with version incompatibility errors
```
Error: nu:🐚:plugin_failed_to_load
× Plugin `polars` is compiled for nushell version 0.107.1, which is not compatible with version 0.108.0
```

**Solution**: Implemented intelligent error classification
- Captures both stdout and stderr from plugin add commands
- Detects version incompatibility: "is not compatible with version" or "is compiled for nushell version"
- Classifies errors into three categories:
  1. **Success**: Plugin registered successfully 
  2. **Incompatible**: Version mismatch (skipped gracefully) ⚠️
  3. **Failed**: Other registration failures 
- Reports summary with counts of each category
- Installation continues successfully even with version mismatches

**New Error Reporting**:
```
 Registered nu_plugin_auth
⚠️  Skipping nu_plugin_polars: Version mismatch (built for different Nushell version)
 Successfully registered 13 plugins
⚠️  Skipped 1 incompatible plugins (version mismatch):
  - nu_plugin_polars
```

**Impact**:
-  No installation failures due to version mismatches
-  Users informed of incompatible plugins
-  Clear distinction between error types
-  Installation completes successfully

#### 0d. Shell Configuration PATH Update - Clear Messaging

**Issue**: Confusing PATH update messages
- User sees: "PATH already updated" for all files
- Then sees: "No shell configuration files were updated" warning
- Then sees: "Please manually add to your PATH" error
- **Problem**: Contradictory messages when PATH is already configured everywhere

**Root Cause**: Script conflated two states
- State 1: "Was PATH found in files?" (skips updating if found)
- State 2: "Did we add PATH to any file?" (used for messaging)
- Both states ignored means no update was made, but PATH might already exist

**Solution**: Track two separate states
```bash
local updated=false        # Was PATH ADDED to any file?
local path_found=false     # Was PATH FOUND in any file?

# In loop:
if grep -q "$install_dir" "$config_file"; then
    path_found=true        # Found it! Mark as true
    continue
fi

# After loop:
if [ "$updated" = "true" ]; then
    log_success "Shell configuration updated"
elif [ "$path_found" = "true" ]; then
    log_success "PATH is already configured in your shell configuration files"
else
    log_warn "Could not find or update shell configuration"
fi
```

**New Clear Messages**:
-  "PATH is already configured in your shell configuration files" (when found everywhere)
-  "Shell configuration updated" (when just added)
- ⚠️ "Could not find or update shell configuration" (when file missing)

**Impact**:
-  Non-contradictory messages
-  Users understand what happened
-  No false warnings when PATH already configured
-  Clear guidance when manual action needed

#### 0e. Installation Features

**`--source-path` Option** (Local Installation):
- Install from local archive: `./install.sh --source-path archive.tar.gz`
- Install from local directory: `./install.sh --source-path /path/to/binaries`
- Default behavior: `./install.sh --source-path` uses `./bin_archives`
- Works with custom `--install-dir` paths
- No download needed, offline installation support

**`--uninstall` with Configuration Management**:
- Prompts user: "Remove ~/.config/nushell? [y/N]"
- Removes all installed binaries and plugins
- Preserves user choice for configuration
- Clean uninstall before fresh reinstall

#### 0f. Documentation Updates

**CLAUDE.md**:
- Added "Install Script Architecture (DRY Design)" section
- Documents source of truth and symlink structure
- Explains `--source-path` feature
- Shows version-agnostic archive detection
- Lists DRY architecture benefits

**README.md**:
- Added "Install Script Architecture (DRY Design)" subsection
- Shows symlink structure with arrows
- Provides `--source-path` usage examples
- Explains version-agnostic detection
- "How DRY Works" 3-step explanation

#### 0g. Files Modified

Core Changes:
- `installers/bootstrap/install.sh` (+3 lines for PATH messaging fix)
  - Archive extraction fix with `-not -path`
  - Plugin registration error classification
  - Clear PATH update messaging
  - Total: 1,247 lines (unified)

Auto-Updated via Symlinks:
- `./install.sh` - Auto-updated (1,247 lines)
- `./scripts/templates/install.sh` - Auto-updated (1,247 lines)

Documentation:
- `CLAUDE.md` - Added install architecture section
- `README.md` - Added install architecture subsection
- `CHANGELOG.md` - Added comprehensive entry (+100 lines)

#### 0h. Testing & Verification

All scenarios tested and verified:
- [x] Archive extraction works with version-agnostic detection
- [x] Installation to `~/.local` successful (16 binaries)
- [x] Installation to `~/.local/bin` successful (21 plugins loaded)
- [x] Plugin registration handles version mismatches gracefully
- [x] PATH messaging is clear and non-contradictory
- [x] Clean uninstall followed by fresh reinstall works perfectly

#### 0i. Impact

User-Facing Benefits:
-  Users can install from any version of nushell-full archive
-  Version mismatch plugins skipped without breaking installation
-  Clear, honest error messages
-  Non-confusing PATH update messages
-  Offline installation support via `--source-path`
-  Clean uninstall/reinstall workflow

Developer Benefits:
-  Single source of truth eliminates code duplication
-  Changes propagate automatically through symlinks
-  Reduced maintenance burden
-  Consistent behavior across all paths
-  Production-ready installation process

---

### 1. Help System Integration (New Feature)

**Issue**: Version-update module recipes were not discoverable
- Not shown in `just help modules`
- Not referenced in `just help`
- Not included in help navigation system
- Users had to manually run `just --list` to find update commands

**Solution**:
- Added version-update module to all help outputs
- Updated `justfiles/help.just` to document all 30+ version-update recipes
- Created new `just commands` recipe as discoverable alias for `just --list`
- Integrated version-update into help-all workflow

**Impact**:
- Version-update commands now fully discoverable via help system
- Users can find update commands with: `just help modules`, `just help`, `just commands`
- Improved overall help system navigation

**Files Modified**:
- `justfiles/help.just` (+23 lines)
  - Added version-update module to help sections
  - Added to modules list
  - Added to help-all workflow
  - New `commands` recipe showing all recipes by group

### 2. Build Process Fixes (Phase 3: Bin Archives)

#### 2a. Plugin Archive Collection Bug

**Issue**: "No plugins found to package" warning in Phase 3
- Collected 26 plugin binaries but reported 0
- Archive creation skipped because count was wrong

**Root Cause**: `each` command returns null, so `| length` returned 0
```nushell
#  OLD - each returns null
let plugin_count = (ls nu_plugin_*/target/release/nu_plugin_* | each {|p|
    cp $p.name $"($temp_dir)/"
} | length)  # Returns 0!
```

**Solution**: Separated counting from copying with proper filtering
```nushell
#  NEW - count before operations
let plugins_to_copy = (ls nu_plugin_*/target/release/nu_plugin_* | where type == "file")
let plugin_count = ($plugins_to_copy | length)
```

**Impact**:
- Now correctly collects and reports 26 plugins
- Filters out .d dependency files automatically
- Warning eliminated

#### 2b. Tar Archive Path Handling

**Issue**: Tar command failing silently with relative paths in subshell
- `cd $temp_dir` changes context unpredictably
- Relative path `../$archive_name` fails in subshell
- Archive file not created despite exit code 0

**Root Cause**: Shell context and relative path issues in Nushell `do` block

**Solution**: Used `tar -C` with absolute paths instead of `cd`
```nushell
#  OLD - unreliable context switching
do {
    cd $temp_dir
    tar -czf ../$archive_name .
}

#  NEW - absolute paths, no context switching
tar -C $temp_dir -czf $archive_path .
```

**Additional Improvements**:
- Absolute path construction using `pwd | path join`
- Better error diagnostics with exit code and stderr output
- File verification after creation

**Impact**:
- Tar archives now created successfully
- Robust path handling across platforms
- Clear error messages for debugging

#### 2c. File Size Calculation Type Error

**Issue**: Runtime error when calculating archive size
```
Error: The '/' operator does not work on values of type 'list<filesize>'
```

**Root Cause**: `ls` returns list of records, so `.size` was a list
```nushell
#  OLD - returns list<filesize>
(ls $archive_path).size / 1024 / 1024

#  NEW - returns filesize
(ls $archive_path | get 0.size) / 1024 / 1024
```

**Impact**:
- Proper file size calculation in MB
- No more type errors

**Files Modified**:
- `scripts/create_full_distribution.nu` (+58 lines, refactored plugin collection)
  - Fixed plugin counting logic
  - Improved path handling with absolute paths
  - Enhanced error diagnostics

### 3. Plugin Rebuild Optimization

**Issue**: All plugins marked for rebuild even when dependencies unchanged
- Step 4 (`update_all_plugins.nu`) touched all Cargo.toml files at 01:00:32
- Step 5 saw all files as "newer" than binaries
- Marked ALL plugins for rebuild, though cargo only rebuilt changed ones

**Root Cause**: Script always saved files, even when no changes made
```nushell
#  OLD - always saves, touching file timestamp
$updated_content | to toml | save -f $cargo_toml
```

**Solution**: Only save if content actually changed
```nushell
#  NEW - compare before writing
let original_toml = $content | to toml
let new_toml = $updated_content | to toml

if $original_toml != $new_toml {
    $updated_content | to toml | save -f $cargo_toml
}
```

**Impact**:
- Unchanged files preserve original timestamps
- Only plugins with actual dependency changes are rebuilt
- Efficient rebuild process with accurate file modification detection

**Files Modified**:
- `scripts/update_all_plugins.nu` (+12 lines, added content comparison)
  - Only touches files with real changes
  - Preserves timestamps for efficiency
  - Clearer logic and comments

### 4. Documentation

**Files Modified**:
- `CHANGELOG.md` (+56 lines)
  - Added comprehensive 2025-10-19 entry
  - Documented all fixes with root causes
  - Listed files modified and impact summary

## Technical Details

### Nushell Patterns Used

1. **Proper List Handling**:
   - `ls` returns list of records, access with `| get 0.size`
   - Filter with `where type == "file"` to exclude metadata

2. **Absolute Path Construction**:
   - `pwd | append "path" | path join` for cross-platform paths
   - Safer than string concatenation with `/`

3. **Content Comparison**:
   - Compare TOML string representation before saving
   - Preserves file timestamps for efficiency

4. **Error Diagnostics**:
   - Capture `stderr` from commands
   - Report exit codes and error messages separately

## Testing

- [x] Help system shows version-update module
- [x] `just commands` displays all recipes by group
- [x] Phase 3 bin archive creation works
- [x] Plugin collection reports correct count (26)
- [x] Tar archives created successfully
- [x] File size calculated correctly
- [x] Plugin rebuild only touches changed files
- [x] CHANGELOG updated with all changes

## Files Changed

```
38 files changed, 2721 insertions(+), 2548 deletions(-)

Core Changes:
- justfiles/help.just                  (+23)  Help system integration
- scripts/create_full_distribution.nu  (+58)  Build process fixes
- scripts/update_all_plugins.nu        (+12)  Rebuild optimization
- CHANGELOG.md                         (+56)  Documentation

Dependency Updates:
- All plugin Cargo.toml and Cargo.lock files (version consistency)
```

## Breaking Changes

None. These are bug fixes and optimizations that maintain backward compatibility.

## Migration Notes

No migration needed. Improvements are transparent to users.

## Related Issues

- Help system discoverability
- Build process Phase 3 failures
- Unnecessary plugin rebuilds
- Build process reliability

## Checklist

- [x] Changes follow Rust/Nushell idioms
- [x] Code is well-commented
- [x] Error handling is comprehensive
- [x] Documentation is updated
- [x] All changes tested
- [x] No breaking changes introduced
2025-10-19 02:39:31 +01:00
..
2025-10-19 02:39:31 +01:00

Nushell + Plugins Bootstrap Installers

Universal installers for Nushell and plugins that work without any prerequisites. These scripts solve the bootstrap problem by providing one-command installation that works on fresh systems.

Quick Start

Linux/macOS (POSIX Shell)

curl -L https://your-url/install.sh | sh

Windows (PowerShell)

Invoke-WebRequest -Uri "https://your-url/install.ps1" | Invoke-Expression

Features

  • Zero Prerequisites: Works on fresh systems without Rust, Git, or other dependencies
  • Multi-Platform: Supports Linux, macOS, and Windows (x86_64, ARM64)
  • Complete Distribution: Installs Nushell + all workspace and custom plugins
  • Automatic Configuration: Sets up PATH, creates default config, registers plugins
  • Installation Modes: User (~/.local/bin) or system (/usr/local/bin) installation
  • Build Options: Pre-built binaries or build from source
  • Verification: Optional installation verification and testing
  • Uninstallation: Clean removal of all installed components

Installation Options

Basic Installation

Default installation to user directory with all plugins:

# Linux/macOS
curl -L install-url/install.sh | sh

# Windows
iwr install-url/install.ps1 | iex

System Installation

Install to system directories (requires admin privileges):

# Linux/macOS (requires sudo)
curl -L install-url/install.sh | sudo sh -s -- --system

# Windows (requires admin PowerShell)
iwr install-url/install.ps1 | iex -ArgumentList "-System"

Build from Source

Build Nushell and plugins from source code:

# Linux/macOS
curl -L install-url/install.sh | sh -s -- --build-from-source

# Windows
iwr install-url/install.ps1 | iex -ArgumentList "-BuildFromSource"

Minimal Installation

Install only Nushell without plugins:

# Linux/macOS
curl -L install-url/install.sh | sh -s -- --no-plugins

# Windows
iwr install-url/install.ps1 | iex -ArgumentList "-NoPlugins"

Command Line Options

Linux/macOS (install.sh)

Option Description
--system Install to system directory (/usr/local/bin, requires sudo)
--user Install to user directory (~/.local/bin) [default]
--no-path Don't modify shell PATH configuration
--no-config Don't create initial nushell configuration
--no-plugins Install only nushell, skip plugins
--build-from-source Build from source instead of downloading binaries
--verify Verify installation after completion
--uninstall Remove nushell and plugins
--version VERSION Install specific version (default: latest)
--help Show help message

Windows (install.ps1)

Parameter Description
-System Install to system directory (C:\Program Files\Nushell, requires admin)
-User Install to user directory (~.local\bin) [default]
-NoPath Don't modify PATH environment variable
-NoConfig Don't create initial nushell configuration
-NoPlugins Install only nushell, skip plugins
-BuildFromSource Build from source instead of downloading binaries
-Verify Verify installation after completion
-Uninstall Remove nushell and plugins
-Version <version> Install specific version (default: latest)
-Help Show help message

Installation Locations

User Installation (Default)

  • Linux/macOS: ~/.local/bin
  • Windows: %USERPROFILE%\.local\bin
  • No admin privileges required
  • Affects only current user

System Installation

  • Linux/macOS: /usr/local/bin
  • Windows: C:\Program Files\Nushell\bin
  • Requires admin privileges
  • Available to all users

Configuration Directory

  • Linux/macOS: ~/.config/nushell
  • Windows: %USERPROFILE%\.config\nushell

What Gets Installed

Core Components

  • nushell binary: Main shell executable
  • Workspace plugins: Built-in nushell plugins
    • nu_plugin_custom_values
    • nu_plugin_example
    • nu_plugin_formats
    • nu_plugin_gstat
    • nu_plugin_inc
    • nu_plugin_polars
    • nu_plugin_query
    • nu_plugin_stress_internals
  • Custom plugins: Additional community plugins
    • nu_plugin_clipboard
    • nu_plugin_desktop_notifications
    • nu_plugin_hashes
    • nu_plugin_highlight
    • nu_plugin_image
    • nu_plugin_kcl
    • nu_plugin_tera
    • And more...

Configuration Files

  • config.nu: Main nushell configuration
  • env.nu: Environment configuration
  • Scripts directory for custom commands
  • Plugins directory for plugin configurations

PATH Integration

Automatically updates shell configuration files:

  • Bash: ~/.bashrc, ~/.bash_profile
  • Zsh: ~/.zshrc
  • Fish: ~/.config/fish/config.fish
  • Nushell: ~/.config/nushell/env.nu
  • Generic: ~/.profile
  • Windows: System/User PATH environment variable

Examples

Standard Installation with Verification

# Linux/macOS
curl -L install-url/install.sh | sh -s -- --verify

# Windows
iwr install-url/install.ps1 | iex -ArgumentList "-Verify"

Corporate/Enterprise Installation

# System installation without auto-config
curl -L install-url/install.sh | sudo sh -s -- --system --no-config

# Windows system installation
# Run as Administrator:
iwr install-url/install.ps1 | iex -ArgumentList "-System", "-NoConfig"

Development Installation

# Build from source with verification
curl -L install-url/install.sh | sh -s -- --build-from-source --verify

# Windows development
iwr install-url/install.ps1 | iex -ArgumentList "-BuildFromSource", "-Verify"

Specific Version Installation

# Install specific version
curl -L install-url/install.sh | sh -s -- --version v0.107.1

# Windows specific version
iwr install-url/install.ps1 | iex -ArgumentList "-Version", "v0.107.1"

Troubleshooting

Common Issues

"Command not found" after installation

  • Restart your terminal/command prompt
  • Or reload shell configuration: source ~/.bashrc (Linux/macOS)
  • Check if installation directory is in PATH

Permission denied errors

  • For system installation, ensure you have admin privileges
  • Use sudo on Linux/macOS or run PowerShell as Administrator on Windows
  • Try user installation instead: --user or -User

Download failures

  • Check internet connection
  • Try building from source: --build-from-source or -BuildFromSource
  • Manual download: Save installer script and run locally

Plugin registration failures

  • Verify nushell binary works: nu --version
  • Try manual plugin registration: nu -c "plugin add /path/to/plugin"
  • Check plugin binary permissions (should be executable)

Build from Source Issues

Missing dependencies

Install required tools:

Linux (Ubuntu/Debian):

sudo apt update
sudo apt install git curl build-essential
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Linux (RHEL/CentOS/Fedora):

sudo dnf install git curl gcc
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

macOS:

# Install Xcode command line tools
xcode-select --install

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Windows:

  1. Install Git from https://git-scm.com/
  2. Install Rust from https://rustup.rs/
  3. Install Visual Studio Build Tools

Verification Steps

Test your installation:

# Check nushell version
nu --version

# Test basic functionality
nu -c "echo 'Hello from Nushell'"

# List installed plugins
nu -c "plugin list"

# Check PATH
which nu    # Linux/macOS
where nu    # Windows

Uninstallation

Complete Removal

# Linux/macOS
curl -L install-url/install.sh | sh -s -- --uninstall

# Windows
iwr install-url/install.ps1 | iex -ArgumentList "-Uninstall"

Manual Removal

  1. Remove binaries from installation directory
  2. Remove configuration directory (optional)
  3. Remove PATH entries from shell configuration files
  4. Remove environment variable modifications (Windows)

Security Considerations

Script Verification

Before running any installer, you should:

  1. Review the script source code
  2. Verify the download URL and SSL certificate
  3. Check script signatures if available
  4. Consider downloading and running locally instead of piping

Permissions

  • User installations don't require admin privileges
  • System installations require elevated privileges
  • Scripts only modify necessary files and directories
  • No automatic execution of arbitrary code from external sources

Network Security

  • Scripts use HTTPS for all downloads
  • Verify SSL certificates before downloading
  • Consider using corporate proxies or mirrors
  • Firewall may need to allow downloads from GitHub/your hosting

Distribution Details

Binary Packages

Pre-built binaries are available for:

  • Linux x86_64 (GNU libc)
  • Linux aarch64 (GNU libc)
  • macOS x86_64 (Intel)
  • macOS arm64 (Apple Silicon)
  • Windows x86_64
  • Windows aarch64

Package Structure

nushell-plugins-{platform}-{version}.tar.gz/
├── nu(.exe)                    # Main nushell binary
├── nu_plugin_*(.exe)          # Plugin binaries
├── config/                    # Default configuration
│   ├── config.nu
│   └── env.nu
├── scripts/                   # Installation scripts
├── docs/                      # Documentation
├── LICENSE                    # License file
└── manifest.json              # Package manifest

Contributing

Testing Installers

Test the installers on various platforms:

  1. Fresh VM or container
  2. Different operating system versions
  3. Various shell configurations
  4. With and without prerequisites

Reporting Issues

When reporting problems, include:

  • Operating system and version
  • Shell type and version
  • Installation command used
  • Complete error messages
  • Network/firewall configuration

Improvements

Areas for enhancement:

  • Additional platform support
  • Mirror/CDN support for faster downloads
  • Package manager integration
  • Corporate deployment features
  • Automated testing workflows

License

These bootstrap installers are part of the nushell-plugins project and are licensed under the same terms. See the main project LICENSE file for details.

Support


Happy shell scripting with Nushell! 🚀