# Remote Script Loader A lightweight, intelligent script loader for Deno that enables remote script execution with shell completions, version control, and caching. ## Features - 🚀 **Remote Execution** - Run scripts directly from Git without cloning - 🔄 **Version Control** - Execute scripts from specific branches or tags (`script@v1.0`) - ⚡ **Smart Completions** - Context-aware shell completions with filesystem discovery - 💾 **Intelligent Caching** - HTTP caching with ETag/Last-Modified support - 🔒 **Fast Daemon** - Background daemon for instant completions (< 15ms) - 📦 **Zero Config** - Works out of the box with bash and zsh ## Quick Start ### Installation Add to your `~/.bashrc` or `~/.zshrc`: ```bash # Load remote script loader from main branch export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.kkarolis.lt/Karolis/scripts/raw/branch/main/loader.ts)" ``` Or pin to a specific version: ```bash # Load from a specific tag export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.kkarolis.lt/Karolis/scripts/raw/tag/v1.0.0/loader.ts)" ``` Or use a local copy: ```bash # Load from local file (for development) export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet /path/to/scripts/loader.ts)" ``` ### Using Custom Refs Set the `LOADER_REF` environment variable to use a different default branch: ```bash # Use a development branch by default export LOADER_REF=develop eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.kkarolis.lt/Karolis/scripts/raw/branch/develop/loader.ts)" ``` ### Basic Usage ```bash # List available scripts scripts # Run a script scripts configure_ssh_key user@host --key=~/.ssh/id_rsa # Run script from a specific branch scripts configure_ssh_key@develop user@host # Run script from a specific tag scripts configure_ssh_key@v1.0.0 user@host ``` ### Shell Completions Press `TAB` to get intelligent completions: ```bash scripts # Lists all available scripts scripts conf # Completes to configure_ssh_key scripts configure_ssh_key@ # Lists available branches and tags scripts configure_ssh_key -- # Shows script-specific flags scripts configure_ssh_key --key= # Suggests SSH keys from ~/.ssh/ ``` ## Configuration ### Environment Variables - **`LOADER_REF`** - Default branch/tag to use (default: `main`) - **`SCRIPTS_DAEMON_PORT`** - Force specific port for daemon (default: auto-assign) - **`SCRIPTS_DAEMON_PORT_FILE`** - Port file location (default: `/tmp/scripts-daemon.port`) ### Examples ```bash # Use staging branch by default export LOADER_REF=staging # Force daemon to use specific port export SCRIPTS_DAEMON_PORT=54321 # Custom port file location export SCRIPTS_DAEMON_PORT_FILE=~/.cache/scripts-daemon.port ``` ## How It Works 1. **Initial Load**: When sourced, the loader: - Spawns a background daemon for completions - Fetches the list of available scripts - Defines the `scripts` shell function 2. **Daemon**: A persistent HTTP server that: - Caches script lists and branch/tag information (60s TTL) - Caches script modules with HTTP ETag/Last-Modified (300s TTL) - Provides fast completions (< 15ms after first request) 3. **Execution**: When you run a script: - Validates the script exists on the remote - Downloads and executes it with Deno - All script arguments are passed through ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Shell (bash/zsh) │ │ scripts configure_ssh_key --key=~/.ssh/id_rsa │ └──────────────┬──────────────────────────────────────────────┘ │ ├─ Execution: Direct to Deno │ │ │ └─> Deno runs remote script │ └─ Completion: Query daemon │ ▼ ┌──────────────────────┐ │ Daemon (port 54xxx) │ │ ─────────────────── │ │ • Caches metadata │ │ • Caches modules │ │ • HTTP conditional │ │ requests (304) │ └──────────────────────┘ │ ├─> Script List API ├─> Branches/Tags API └─> Script Module Import ``` ## Writing Scripts See [COMPLETIONS.md](./COMPLETIONS.md) for a comprehensive guide on adding intelligent completions to your scripts. ### Minimal Example ```typescript #!/usr/bin/env -S deno run --allow-all import type { CompletionContext } from "./completions.d.ts"; // Export completion function (optional) export function getCompletions(ctx: CompletionContext): string[] { return ["--verbose", "--help"]; } // Your script logic console.log("Hello from remote script!"); ``` ### Using Dependencies For remote scripts to work, use explicit JSR imports instead of bare specifiers: ```typescript // ❌ Won't work for remote scripts import { parseArgs } from "@std/cli/parse-args"; // ✅ Use JSR imports for remote execution import { parseArgs } from "jsr:@std/cli@^1.0.0/parse-args"; ``` This ensures dependencies are resolved when the script is executed remotely via URL. ### Async Completions ```typescript export async function getCompletions(ctx: CompletionContext): Promise { const { current } = ctx; if (current.startsWith("--key=")) { // Discover SSH keys asynchronously const keys: string[] = []; for await (const entry of Deno.readDir(`${Deno.env.get("HOME")}/.ssh`)) { if (entry.isFile && entry.name.startsWith("id_")) { keys.push(`--key=~/.ssh/${entry.name}`); } } return keys; } return ["--key=", "--help"]; } ``` ## Performance ### Caching Strategy | Resource | Cache Duration | Strategy | |----------|----------------|----------| | Script List | 60 seconds | In-memory | | Branches/Tags | 60 seconds | In-memory | | Script Modules | 300 seconds | HTTP ETag/Last-Modified | ### Benchmarks - **First completion**: ~120ms (network + parse) - **Cached completion**: ~14ms (8x faster) - **Daemon startup**: ~100ms - **Loader script**: Exits immediately after spawning daemon ## Troubleshooting ### Daemon Not Starting Check if the daemon is running: ```bash ps aux | grep "loader.ts.*daemon" cat /tmp/scripts-daemon.port curl http://127.0.0.1:$(cat /tmp/scripts-daemon.port)/health ``` Restart the daemon: ```bash pkill -f "loader.ts.*daemon" eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet loader.ts)" ``` ### Completions Not Working 1. Verify daemon is running (see above) 2. Check completion function is exported: ```bash deno eval 'const m = await import("file:///path/to/script.ts"); console.log(typeof m.getCompletions)' ``` 3. Test completion function directly: ```bash deno eval 'const m = await import("file:///path/to/script.ts"); console.log(await m.getCompletions({args: [], current: "--", position: 0}))' ``` ### Slow Completions - Check network latency to Git server - Verify caching is working (second request should be faster) - Consider increasing cache TTL in daemon code - Avoid expensive operations in completion functions ### Scripts Not Found ```bash # Check script exists in repository scripts # Verify URL is accessible curl -I https://git.kkarolis.lt/Karolis/scripts/raw/branch/main/script-name.ts # Try with explicit ref scripts script-name@main ``` ## Advanced Usage ### Multiple Script Repositories You can have multiple loader instances with different configurations: ```bash # Personal scripts export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.example.com/me/scripts/raw/branch/main/loader.ts)" alias myscripts='scripts' # Work scripts export LOADER_REF=production eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.company.com/team/scripts/raw/branch/production/loader.ts)" alias workscripts='scripts' ``` ### Development Workflow ```bash # Use local loader for testing cd ~/scripts export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet ./loader.ts)" # Test your script scripts my-new-script --help # Push and use remote version git push export LOADER_REF=main eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet https://git.kkarolis.lt/Karolis/scripts/raw/branch/main/loader.ts)" scripts my-new-script@main --help ``` ## Files in This Repository - **`loader.ts`** - Main loader script with daemon - **`completions.d.ts`** - TypeScript definitions for completion functions - **`COMPLETIONS.md`** - Comprehensive guide for script developers - **`configure_ssh_key.ts`** - Example script with advanced completions - **`README.md`** - This file ## Requirements - [Deno](https://deno.land/) 1.30+ installed - Bash or Zsh shell - Network access to Git server - `curl` for health checks (in completion functions) ## License MIT