From b08e931de4771d445e7bd3afbd3e5ae5c1ecc82f Mon Sep 17 00:00:00 2001 From: Juantomas Garcia Date: Wed, 1 Jul 2026 10:16:27 +0200 Subject: [PATCH 1/4] feat: add dependency-free install.sh (curl | sh) for install/update without just --- install.sh | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100755 install.sh diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..6fd99bd --- /dev/null +++ b/install.sh @@ -0,0 +1,122 @@ +#!/bin/sh +# ralph installer / updater — no dependencies beyond curl + tar. +# +# Installs ralph-loop.sh to ~/.local/bin and copies the bundled skills +# (juez, maestro, ralph) into Claude Code, Codex CLI and Antigravity CLI, +# exactly like `just install` + `just skills-install`, but without `just`. +# +# Quick use: +# curl -fsSL https://raw.githubusercontent.com/SantanderAI/ralph/main/install.sh | sh +# +# Options (flags or env vars): +# --no-skills Install only the script, skip skills. +# (env: RALPH_SKIP_SKILLS=1) +# --ref Git ref to install from. (env: RALPH_REF, default: main) +# --repo Source repository. (env: RALPH_REPO, default: SantanderAI/ralph) +# --install-dir Where to put the script. (env: RALPH_INSTALL_DIR, default: ~/.local/bin) +# +# Examples: +# curl -fsSL .../install.sh | sh -s -- --no-skills +# RALPH_REF=dev curl -fsSL .../install.sh | sh + +set -eu + +REPO="${RALPH_REPO:-SantanderAI/ralph}" +REF="${RALPH_REF:-main}" +INSTALL_DIR="${RALPH_INSTALL_DIR:-$HOME/.local/bin}" +SKIP_SKILLS="${RALPH_SKIP_SKILLS:-0}" +SCRIPT="ralph-loop.sh" + +while [ $# -gt 0 ]; do + case "$1" in + --no-skills) SKIP_SKILLS=1 ;; + --ref) REF="${2:?--ref needs a value}"; shift ;; + --repo) REPO="${2:?--repo needs a value}"; shift ;; + --install-dir) INSTALL_DIR="${2:?--install-dir needs a value}"; shift ;; + -h|--help) sed -n '2,25p' "$0" 2>/dev/null || echo "See header of install.sh"; exit 0 ;; + *) echo "Unknown option: $1" >&2; exit 2 ;; + esac + shift +done + +for dep in curl tar; do + command -v "$dep" >/dev/null 2>&1 || { echo "Error: '$dep' is required." >&2; exit 1; } +done + +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT INT TERM + +echo "Fetching $REPO@$REF ..." +url="https://codeload.github.com/$REPO/tar.gz/$REF" +if ! curl -fsSL "$url" -o "$tmp/src.tar.gz"; then + echo "Error: download failed (does ref '$REF' exist in $REPO?): $url" >&2 + exit 1 +fi +if ! tar xzf "$tmp/src.tar.gz" -C "$tmp"; then + echo "Error: could not extract the downloaded archive." >&2 + exit 1 +fi +rm -f "$tmp/src.tar.gz" + +src="$tmp/$(ls -1 "$tmp" | head -n1)" +if [ ! -f "$src/$SCRIPT" ]; then + echo "Error: $SCRIPT not found in the downloaded archive." >&2 + exit 1 +fi + +# --- Install the script ----------------------------------------------------- +mkdir -p "$INSTALL_DIR" +cp "$src/$SCRIPT" "$INSTALL_DIR/$SCRIPT" +chmod +x "$INSTALL_DIR/$SCRIPT" +echo "Installed $INSTALL_DIR/$SCRIPT" + +case ":$PATH:" in + *":$INSTALL_DIR:"*) ;; + *) + echo "" + echo "WARNING: $INSTALL_DIR is not in your PATH." + echo "Add this to your shell config (~/.zshrc or ~/.bashrc):" + echo "" + echo " export PATH=\"$INSTALL_DIR:\$PATH\"" + echo "" + ;; +esac + +# --- Install the skills ----------------------------------------------------- +if [ "$SKIP_SKILLS" = "1" ]; then + echo "Skipping skills (--no-skills)." + exit 0 +fi + +if [ ! -d "$src/skills" ]; then + echo "No skills/ directory in the archive; nothing else to do." + exit 0 +fi + +CODEX_HOME="${CODEX_HOME:-$HOME/.codex}" +SKILL_TARGETS="$HOME/.claude/skills $CODEX_HOME/skills $HOME/.gemini/antigravity-cli/skills" + +installed_any=0 +for dir in "$src"/skills/*/; do + [ -f "$dir/SKILL.md" ] || continue + name="$(basename "$dir")" + for target in $SKILL_TARGETS; do + mkdir -p "$target" + rm -rf "$target/$name" + if command -v rsync >/dev/null 2>&1; then + rsync -a "$dir" "$target/$name/" + else + mkdir -p "$target/$name" + cp -R "$dir." "$target/$name/" + fi + echo " skill $name -> $target/$name" + installed_any=1 + done +done + +if [ "$installed_any" -eq 0 ]; then + echo "No skills found under skills//SKILL.md." +else + echo "" + echo "Done. Restart Codex and Antigravity to pick up the skills." +fi From 91a684e11dfe598d2484b338ddce2061b57a895a Mon Sep 17 00:00:00 2001 From: Juantomas Garcia Date: Wed, 1 Jul 2026 10:17:49 +0200 Subject: [PATCH 2/4] docs(readme): document curl | sh install/update method --- README.md | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a17883..539c282 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,23 @@ should tell the agent to read that state and make incremental progress. ## Installation -Install the script to `~/.local/bin`: +The quickest way — a dependency-free installer (needs only `curl` and `tar`) +that copies `ralph-loop.sh` to `~/.local/bin` and installs the bundled skills. +Re-run it any time to update: + +```sh +curl -fsSL https://raw.githubusercontent.com/SantanderAI/ralph/main/install.sh | sh +``` + +It accepts `--no-skills`, `--ref `, `--repo ` and +`--install-dir ` (also available as the `RALPH_SKIP_SKILLS`, `RALPH_REF`, +`RALPH_REPO` and `RALPH_INSTALL_DIR` environment variables), e.g.: + +```sh +curl -fsSL https://raw.githubusercontent.com/SantanderAI/ralph/main/install.sh | sh -s -- --no-skills +``` + +Alternatively, from a clone with [`just`](https://github.com/casey/just): ```sh just install From d9f89c8d4b060b05e346d7ea0e27c7ff3f162a45 Mon Sep 17 00:00:00 2001 From: Juantomas Garcia Date: Wed, 1 Jul 2026 10:22:31 +0200 Subject: [PATCH 3/4] feat: add PowerShell installer install.ps1 (irm | iex) with parity to install.sh --- README.md | 9 +++++ install.ps1 | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 install.ps1 diff --git a/README.md b/README.md index 539c282..7334114 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,15 @@ It accepts `--no-skills`, `--ref `, `--repo ` and curl -fsSL https://raw.githubusercontent.com/SantanderAI/ralph/main/install.sh | sh -s -- --no-skills ``` +On **Windows / PowerShell** (pwsh 6+), the equivalent installs `ralph-loop.ps1`: + +```powershell +powershell -c "irm https://raw.githubusercontent.com/SantanderAI/ralph/main/install.ps1 | iex" +``` + +The PowerShell installer is configured through the same `RALPH_SKIP_SKILLS`, +`RALPH_REF`, `RALPH_REPO` and `RALPH_INSTALL_DIR` environment variables. + Alternatively, from a clone with [`just`](https://github.com/casey/just): ```sh diff --git a/install.ps1 b/install.ps1 new file mode 100644 index 0000000..fb69c26 --- /dev/null +++ b/install.ps1 @@ -0,0 +1,111 @@ +#!/usr/bin/env pwsh +# Copyright (c) 2026 César Gallego Rodríguez +# SPDX-License-Identifier: Apache-2.0 +# +# ralph installer / updater for PowerShell (pwsh 6+). +# +# Installs ralph-loop.ps1 to ~/.local/bin and copies the bundled skills +# (juez, maestro, ralph) into Claude Code, Codex CLI and Antigravity CLI, +# mirroring install.sh. Re-run it any time to update. +# +# Quick use: +# powershell -c "irm https://raw.githubusercontent.com/SantanderAI/ralph/main/install.ps1 | iex" +# +# Configuration via environment variables (works with the `irm | iex` form): +# RALPH_SKIP_SKILLS Set to 1 to install only the script, skipping skills. +# RALPH_REF Git ref to install from. (default: main) +# RALPH_REPO Source repository. (default: SantanderAI/ralph) +# RALPH_INSTALL_DIR Where to put the script. (default: ~/.local/bin) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$repo = if ($env:RALPH_REPO) { $env:RALPH_REPO } else { 'SantanderAI/ralph' } +$ref = if ($env:RALPH_REF) { $env:RALPH_REF } else { 'main' } +$installDir = if ($env:RALPH_INSTALL_DIR) { $env:RALPH_INSTALL_DIR } else { Join-Path $HOME '.local/bin' } +$skipSkills = [bool]($env:RALPH_SKIP_SKILLS) -and ($env:RALPH_SKIP_SKILLS -ne '0') +$scriptName = 'ralph-loop.ps1' + +$tmp = Join-Path ([System.IO.Path]::GetTempPath()) ('ralph-' + [System.Guid]::NewGuid().ToString('N')) +New-Item -ItemType Directory -Path $tmp | Out-Null +try { + $zip = Join-Path $tmp 'src.zip' + $url = "https://codeload.github.com/$repo/zip/$ref" + Write-Host "Fetching $repo@$ref ..." + try { + Invoke-WebRequest -Uri $url -OutFile $zip + } catch { + throw "Download failed (does ref '$ref' exist in $repo?): $url" + } + Expand-Archive -Path $zip -DestinationPath $tmp -Force + Remove-Item -Path $zip -Force + + $src = Get-ChildItem -Path $tmp -Directory | Select-Object -First 1 + if (-not $src) { throw 'Unexpected archive layout: no extracted directory.' } + + # --- Install the script ------------------------------------------------- + $scriptPath = Join-Path $src.FullName $scriptName + if (-not (Test-Path -Path $scriptPath)) { + throw "$scriptName not found in the downloaded archive." + } + New-Item -ItemType Directory -Path $installDir -Force | Out-Null + $dest = Join-Path $installDir $scriptName + Copy-Item -Path $scriptPath -Destination $dest -Force + Write-Host "Installed $dest" + + $paths = $env:PATH -split [System.IO.Path]::PathSeparator + if ($paths -notcontains $installDir) { + $sep = [System.IO.Path]::PathSeparator + Write-Host '' + Write-Host "WARNING: $installDir is not in your PATH." + Write-Host 'Add it to your PowerShell profile:' + Write-Host '' + Write-Host " `$env:PATH = `"$installDir$sep`$env:PATH`"" + Write-Host '' + } + + # --- Install the skills ------------------------------------------------- + if ($skipSkills) { + Write-Host 'Skipping skills (RALPH_SKIP_SKILLS).' + return + } + + $skillsRoot = Join-Path $src.FullName 'skills' + if (-not (Test-Path -Path $skillsRoot)) { + Write-Host 'No skills/ directory in the archive; nothing else to do.' + return + } + + $codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $HOME '.codex' } + $targets = @( + (Join-Path $HOME '.claude/skills'), + (Join-Path $codexHome 'skills'), + (Join-Path $HOME '.gemini/antigravity-cli/skills') + ) + + $installedAny = $false + foreach ($skillDir in Get-ChildItem -Path $skillsRoot -Directory) { + if (-not (Test-Path -Path (Join-Path $skillDir.FullName 'SKILL.md'))) { continue } + $name = $skillDir.Name + foreach ($target in $targets) { + New-Item -ItemType Directory -Path $target -Force | Out-Null + $skillDest = Join-Path $target $name + if (Test-Path -Path $skillDest) { + Remove-Item -Path $skillDest -Recurse -Force + } + Copy-Item -Path $skillDir.FullName -Destination $skillDest -Recurse -Force + Write-Host " skill $name -> $skillDest" + $installedAny = $true + } + } + + if ($installedAny) { + Write-Host '' + Write-Host 'Done. Restart Codex and Antigravity to pick up the skills.' + } else { + Write-Host 'No skills found under skills//SKILL.md.' + } +} +finally { + Remove-Item -Path $tmp -Recurse -Force -ErrorAction SilentlyContinue +} From 467aa6d095c4f0bf2ec98afc3409108da1060c48 Mon Sep 17 00:00:00 2001 From: Juantomas Garcia Date: Wed, 1 Jul 2026 10:54:33 +0200 Subject: [PATCH 4/4] fix: add SPDX-License-Identifier header to install.sh --- install.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install.sh b/install.sh index 6fd99bd..cc2c902 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,7 @@ #!/bin/sh +# Copyright (c) 2026 César Gallego Rodríguez +# SPDX-License-Identifier: Apache-2.0 +# # ralph installer / updater — no dependencies beyond curl + tar. # # Installs ralph-loop.sh to ~/.local/bin and copies the bundled skills