docs: streamline install process with one-line installer scripts and update documentation

- Add markdown file triggers to GitHub workflow
- Update VSCode settings with new spell entries
- Simplify README installation with one-line installers
- Add bash installer script for Unix systems
- Add PowerShell installer script for Windows
- Create installer documentation with usage examples
- Remove redundant pattern from pattern explanations
This commit is contained in:
Kayvan Sylvan
2025-09-01 11:12:42 -07:00
parent d205dbcdac
commit fad176a0a8
8 changed files with 660 additions and 77 deletions

114
scripts/installer/README.md Normal file
View File

@@ -0,0 +1,114 @@
# Fabric One-Line Installer
This directory contains the official one-line installer scripts for Fabric.
## Quick Start
### Unix/Linux/macOS
Install Fabric with a single command:
```bash
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | bash
```
### Windows (PowerShell)
Install Fabric with a single PowerShell command:
```powershell
iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
```
## Custom Installation Directory
### Unix/Linux/macOS
By default, Fabric is installed to `~/.local/bin`. To install elsewhere:
```bash
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | INSTALL_DIR=/usr/local/bin bash
```
For system-wide installation (requires sudo):
```bash
curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | sudo INSTALL_DIR=/usr/local/bin bash
```
### Windows (PowerShell)
By default, Fabric is installed to `%USERPROFILE%\.local\bin`. To install elsewhere:
```powershell
$env:INSTALL_DIR="C:\tools"; iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
```
## Supported Systems
- **Operating Systems**: Darwin (macOS), Linux, Windows
- **Architectures**: x86_64, arm64, i386 (Windows only)
## What It Does
1. **Detects** your OS and architecture automatically
2. **Downloads** the latest Fabric release from GitHub
3. **Extracts** only the `fabric` binary (not the full archive)
4. **Installs** to your chosen directory (default: `~/.local/bin`)
5. **Verifies** the installation works correctly
6. **Provides** PATH setup instructions if needed
## Features
-**Cross-platform** - Unix/Linux/macOS (bash) and Windows (PowerShell)
-**Zero dependencies** - No additional tools required
-**Automatic detection** - OS and architecture
-**Smart extraction** - Only the binary, not extra files
-**Error handling** - Clear messages and graceful failures
-**PATH guidance** - Helps you set up your environment
-**Verification** - Tests the installation before completing
## Requirements
### Unix/Linux/macOS
- `curl` or `wget` for downloading
- `tar` for extraction (standard on all Unix systems)
- Write permissions to the installation directory
### Windows
- PowerShell (built into Windows)
- Write permissions to the installation directory
## After Installation
1. **Configure Fabric**: Run `fabric --setup`
2. **Add API keys**: Follow the setup prompts
3. **Start using**: Try `fabric --help` or `fabric --listpatterns`
## Troubleshooting
**Permission denied?**
- Try with `sudo` for system directories
- Or choose a directory you can write to: `INSTALL_DIR=~/bin`
**Binary not found after install?**
- Add the install directory to your PATH
- The installer provides specific instructions for your shell
**Download fails?**
- Check your internet connection
- Verify GitHub is accessible from your network
## Alternative Installation Methods
If the one-liner doesn't work for you, see the main [Installation Guide](../../README.md#installation) for:
- Binary downloads
- Package managers (Homebrew, winget, AUR)
- Docker images
- Building from source

View File

@@ -0,0 +1,253 @@
# Fabric Windows Installer Script
# Usage: iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
# Usage with custom directory: $env:INSTALL_DIR="C:\tools"; iwr -useb https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.ps1 | iex
param(
[string]$InstallDir = $env:INSTALL_DIR
)
$ErrorActionPreference = "Stop"
# Colors for output (Windows Console colors)
$Colors = @{
Red = "Red"
Green = "Green"
Yellow = "Yellow"
Blue = "Cyan"
White = "White"
}
# Print functions
function Write-Info {
param([string]$Message)
Write-Host "[INFO] $Message" -ForegroundColor $Colors.Blue
}
function Write-Success {
param([string]$Message)
Write-Host "[SUCCESS] $Message" -ForegroundColor $Colors.Green
}
function Write-Warning {
param([string]$Message)
Write-Host "[WARNING] $Message" -ForegroundColor $Colors.Yellow
}
function Write-Error {
param([string]$Message)
Write-Host "[ERROR] $Message" -ForegroundColor $Colors.Red
}
# Detect Windows architecture
function Get-Architecture {
$arch = $env:PROCESSOR_ARCHITECTURE
$archAMD64 = $env:PROCESSOR_ARCHITEW6432
# Check for ARM64
if ($arch -eq "ARM64") {
return "arm64"
}
# Check for x86_64/AMD64
if ($arch -eq "AMD64" -or $archAMD64 -eq "AMD64") {
return "x86_64"
}
# Check for x86 (32-bit)
if ($arch -eq "X86") {
return "i386"
}
Write-Error "Unsupported architecture: $arch"
Write-Error "This installer supports x86_64, i386, and arm64"
exit 1
}
# Test if running with appropriate permissions for directory
function Test-WritePermission {
param([string]$Path)
try {
if (!(Test-Path $Path)) {
New-Item -Path $Path -ItemType Directory -Force | Out-Null
}
$testFile = Join-Path $Path "fabric_write_test.tmp"
"test" | Out-File -FilePath $testFile -Force
Remove-Item $testFile -Force
return $true
}
catch {
return $false
}
}
# Download and install Fabric
function Install-Fabric {
param(
[string]$Architecture,
[string]$InstallDirectory
)
# Construct download URL
$filename = "fabric_Windows_$Architecture.zip"
$downloadUrl = "https://github.com/danielmiessler/fabric/releases/latest/download/$filename"
Write-Info "Downloading Fabric for Windows $Architecture..."
Write-Info "URL: $downloadUrl"
# Create temporary directory
$tempDir = Join-Path $env:TEMP "fabric_install_$(Get-Random)"
New-Item -Path $tempDir -ItemType Directory -Force | Out-Null
$tempFile = Join-Path $tempDir "fabric.zip"
try {
# Download the archive
Write-Info "Downloading archive..."
Invoke-WebRequest -Uri $downloadUrl -OutFile $tempFile -UseBasicParsing
Write-Info "Extracting Fabric binary..."
# Extract the zip file
Add-Type -AssemblyName System.IO.Compression.FileSystem
$zip = [System.IO.Compression.ZipFile]::OpenRead($tempFile)
# Find and extract only fabric.exe
$fabricEntry = $zip.Entries | Where-Object { $_.Name -eq "fabric.exe" }
if (!$fabricEntry) {
Write-Error "fabric.exe not found in the downloaded archive"
exit 1
}
# Create install directory if it doesn't exist
if (!(Test-Path $InstallDirectory)) {
Write-Info "Creating install directory: $InstallDirectory"
New-Item -Path $InstallDirectory -ItemType Directory -Force | Out-Null
}
# Extract fabric.exe to install directory
$fabricPath = Join-Path $InstallDirectory "fabric.exe"
Write-Info "Installing Fabric to $fabricPath..."
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($fabricEntry, $fabricPath, $true)
$zip.Dispose()
Write-Success "Fabric installed successfully to $fabricPath"
return $fabricPath
}
catch {
Write-Error "Failed to download or extract Fabric: $($_.Exception.Message)"
exit 1
}
finally {
# Clean up
if (Test-Path $tempDir) {
Remove-Item $tempDir -Recurse -Force -ErrorAction SilentlyContinue
}
}
}
# Check if directory is in PATH
function Test-InPath {
param([string]$Directory)
$pathDirs = $env:PATH -split ';'
return $pathDirs -contains $Directory
}
# Provide PATH setup instructions
function Show-PathInstructions {
param([string]$InstallDir)
if (Test-InPath $InstallDir) {
Write-Success "$InstallDir is already in your PATH"
}
else {
Write-Warning "⚠️ $InstallDir is not in your PATH"
Write-Info "To use fabric from anywhere, you have a few options:"
Write-Info ""
Write-Info "Option 1 - Add to PATH for current user (recommended):"
Write-Info " `$currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')"
Write-Info " [Environment]::SetEnvironmentVariable('PATH', `"`$currentPath;$InstallDir`", 'User')"
Write-Info ""
Write-Info "Option 2 - Add to PATH for all users (requires admin):"
Write-Info " `$currentPath = [Environment]::GetEnvironmentVariable('PATH', 'Machine')"
Write-Info " [Environment]::SetEnvironmentVariable('PATH', `"`$currentPath;$InstallDir`", 'Machine')"
Write-Info ""
Write-Info "Option 3 - Add to current session only:"
Write-Info " `$env:PATH += `";$InstallDir`""
Write-Info ""
Write-Info "After updating PATH, restart your terminal or run: refreshenv"
}
}
# Verify installation
function Test-Installation {
param([string]$FabricPath)
if (Test-Path $FabricPath) {
Write-Info "Verifying installation..."
try {
$version = & $FabricPath --version 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Success "Fabric $version is working correctly!"
}
else {
Write-Warning "Fabric binary exists but --version failed"
}
}
catch {
Write-Warning "Fabric binary exists but could not run --version"
}
}
else {
Write-Error "Fabric binary not found at $FabricPath"
exit 1
}
}
# Main installation function
function Main {
Write-Info "🚀 Starting Fabric installation..."
# Detect architecture
$arch = Get-Architecture
Write-Info "Detected architecture: $arch"
# Determine install directory
if (!$InstallDir) {
$InstallDir = Join-Path $env:USERPROFILE ".local\bin"
}
Write-Info "Install directory: $InstallDir"
# Check permissions
if (!(Test-WritePermission $InstallDir)) {
Write-Error "Cannot write to $InstallDir"
Write-Error "Try running as Administrator or choose a different directory"
Write-Info "Example with custom directory: `$env:INSTALL_DIR=`"C:\tools`"; iwr -useb ... | iex"
exit 1
}
# Install Fabric
$fabricPath = Install-Fabric -Architecture $arch -InstallDirectory $InstallDir
# Verify installation
Test-Installation -FabricPath $fabricPath
# Check PATH and provide instructions
Show-PathInstructions -InstallDir $InstallDir
Write-Info ""
Write-Success "🎉 Installation complete!"
Write-Info ""
Write-Info "Next steps:"
Write-Info " 1. Run 'fabric --setup' to configure Fabric"
Write-Info " 2. Add your API keys and preferences"
Write-Info " 3. Start using Fabric with 'fabric --help'"
Write-Info ""
Write-Info "Documentation: https://github.com/danielmiessler/fabric"
}
# Run main function
Main

219
scripts/installer/install.sh Executable file
View File

@@ -0,0 +1,219 @@
#!/bin/bash
# Fabric Installer Script
# Usage: curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | bash
# Usage with custom directory: curl -fsSL https://raw.githubusercontent.com/danielmiessler/fabric/main/scripts/installer/install.sh | INSTALL_DIR=/usr/local/bin bash
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Print functions
print_info() {
printf "${BLUE}[INFO]${NC} %s\n" "$1"
}
print_success() {
printf "${GREEN}[SUCCESS]${NC} %s\n" "$1"
}
print_warning() {
printf "${YELLOW}[WARNING]${NC} %s\n" "$1"
}
print_error() {
printf "${RED}[ERROR]${NC} %s\n" "$1" >&2
}
# Detect OS
detect_os() {
case "$(uname -s)" in
Darwin*)
echo "Darwin"
;;
Linux*)
echo "Linux"
;;
*)
print_error "Unsupported operating system: $(uname -s)"
print_error "This installer only supports Darwin (macOS) and Linux"
exit 1
;;
esac
}
# Detect architecture
detect_arch() {
case "$(uname -m)" in
x86_64|amd64)
echo "x86_64"
;;
arm64|aarch64)
echo "arm64"
;;
*)
print_error "Unsupported architecture: $(uname -m)"
print_error "This installer only supports x86_64 and arm64"
exit 1
;;
esac
}
# Check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Download and extract fabric
install_fabric() {
local os="$1"
local arch="$2"
local install_dir="$3"
# Construct download URL
local filename="fabric_${os}_${arch}.tar.gz"
local download_url="https://github.com/danielmiessler/fabric/releases/latest/download/${filename}"
print_info "Downloading Fabric for ${os} ${arch}..."
print_info "URL: ${download_url}"
# Create temporary directory
local temp_dir
temp_dir=$(mktemp -d)
local temp_file="${temp_dir}/fabric.tar.gz"
# Download the archive
if command_exists curl; then
if ! curl -fsSL "${download_url}" -o "${temp_file}"; then
print_error "Failed to download Fabric"
rm -rf "${temp_dir}"
exit 1
fi
elif command_exists wget; then
if ! wget -q "${download_url}" -O "${temp_file}"; then
print_error "Failed to download Fabric"
rm -rf "${temp_dir}"
exit 1
fi
else
print_error "Neither curl nor wget found. Please install one of them and try again."
exit 1
fi
print_info "Extracting Fabric binary..."
# Extract only the fabric binary from the archive
if ! tar -xzf "${temp_file}" -C "${temp_dir}" fabric; then
print_error "Failed to extract Fabric binary"
rm -rf "${temp_dir}"
exit 1
fi
# Create install directory if it doesn't exist
if [ ! -d "${install_dir}" ]; then
print_info "Creating install directory: ${install_dir}"
if ! mkdir -p "${install_dir}"; then
print_error "Failed to create install directory: ${install_dir}"
print_error "You may need to run with sudo or choose a different directory"
rm -rf "${temp_dir}"
exit 1
fi
fi
# Move binary to install directory
print_info "Installing Fabric to ${install_dir}/fabric..."
if ! mv "${temp_dir}/fabric" "${install_dir}/fabric"; then
print_error "Failed to install Fabric to ${install_dir}"
print_error "You may need to run with sudo or choose a different directory"
rm -rf "${temp_dir}"
exit 1
fi
# Make sure it's executable
chmod +x "${install_dir}/fabric"
# Clean up
rm -rf "${temp_dir}"
print_success "Fabric installed successfully to ${install_dir}/fabric"
}
# Check PATH and provide instructions
check_path() {
local install_dir="$1"
if echo "$PATH" | grep -q "${install_dir}"; then
print_success "${install_dir} is already in your PATH"
else
print_warning "⚠️ ${install_dir} is not in your PATH"
print_info "To use fabric from anywhere, add the following to your shell profile:"
print_info " export PATH=\"\$PATH:${install_dir}\""
print_info ""
print_info "For bash, add it to ~/.bashrc or ~/.bash_profile"
print_info "For zsh, add it to ~/.zshrc"
print_info "For fish, run: fish_add_path ${install_dir}"
fi
}
# Verify installation
verify_installation() {
local install_dir="$1"
local fabric_path="${install_dir}/fabric"
if [ -x "${fabric_path}" ]; then
print_info "Verifying installation..."
local version
if version=$("${fabric_path}" --version 2>/dev/null); then
print_success "Fabric ${version} is working correctly!"
else
print_warning "Fabric binary exists but --version failed"
fi
else
print_error "Fabric binary not found at ${fabric_path}"
exit 1
fi
}
# Main installation function
main() {
print_info "🚀 Starting Fabric installation..."
# Detect system
local os
local arch
os=$(detect_os)
arch=$(detect_arch)
print_info "Detected system: ${os} ${arch}"
# Determine install directory
local install_dir="${INSTALL_DIR:-${HOME}/.local/bin}"
print_info "Install directory: ${install_dir}"
# Install fabric
install_fabric "${os}" "${arch}" "${install_dir}"
# Verify installation
verify_installation "${install_dir}"
# Check PATH
check_path "${install_dir}"
print_info ""
print_success "🎉 Installation complete!"
print_info ""
print_info "Next steps:"
print_info " 1. Run 'fabric --setup' to configure Fabric"
print_info " 2. Add your API keys and preferences"
print_info " 3. Start using Fabric with 'fabric --help'"
print_info ""
print_info "Documentation: https://github.com/danielmiessler/fabric"
}
# Run main function
main "$@"