Features: - Remote script execution with version control (name@ref) - Background daemon for fast completions (< 15ms) - HTTP caching with ETag/Last-Modified support - Context-aware completions with async support - Comprehensive documentation and type definitions Changes: - Add loader.ts with daemon mode - Add completions.d.ts type definitions - Add COMPLETIONS.md guide for developers - Add README.md with usage examples - Update configure_ssh_key.ts with async completions - Use JSR imports for remote execution compatibility
9.5 KiB
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:
# 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:
# 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:
# 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:
# 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
# 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:
scripts <TAB> # Lists all available scripts
scripts conf<TAB> # Completes to configure_ssh_key
scripts configure_ssh_key@<TAB> # Lists available branches and tags
scripts configure_ssh_key --<TAB> # Shows script-specific flags
scripts configure_ssh_key --key=<TAB> # 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
# 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
-
Initial Load: When sourced, the loader:
- Spawns a background daemon for completions
- Fetches the list of available scripts
- Defines the
scriptsshell function
-
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)
-
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 <TAB> │
└──────────────┬──────────────────────────────────────────────┘
│
├─ 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 for a comprehensive guide on adding intelligent completions to your scripts.
Minimal Example
#!/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:
// ❌ 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
export async function getCompletions(ctx: CompletionContext): Promise<string[]> {
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:
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:
pkill -f "loader.ts.*daemon"
eval "$(deno run --allow-net --allow-read --allow-env --allow-run --quiet loader.ts)"
Completions Not Working
- Verify daemon is running (see above)
- Check completion function is exported:
deno eval 'const m = await import("file:///path/to/script.ts"); console.log(typeof m.getCompletions)' - Test completion function directly:
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
# 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:
# 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
# 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 daemoncompletions.d.ts- TypeScript definitions for completion functionsCOMPLETIONS.md- Comprehensive guide for script developersconfigure_ssh_key.ts- Example script with advanced completionsREADME.md- This file
Requirements
- Deno 1.30+ installed
- Bash or Zsh shell
- Network access to Git server
curlfor health checks (in completion functions)
License
MIT