Add bin/ module: userland CLI tools into ~/.local/bin
New bin/install.sh downloads self-contained release binaries (ripgrep, fd, bat, fzf, jq) into ~/.local/bin — no sudo, nothing outside $HOME, so they persist across Kasm redeploys with no reinstall. Statically linked where available, so they keep working even after the root fs is wiped. Idempotent: pinned versions already present are skipped. lib/fetch.sh adds arch detection + tarball/raw binary download helpers. zsh/zshrc puts ~/.local/bin on PATH; bootstrap.sh runs the module. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,8 +30,14 @@ Already have a clone? Just run it directly:
|
|||||||
- `git/` — sets git `user.name`/`user.email` and configures
|
- `git/` — sets git `user.name`/`user.email` and configures
|
||||||
`credential.helper store` (plaintext `~/.git-credentials`, 0600) for
|
`credential.helper store` (plaintext `~/.git-credentials`, 0600) for
|
||||||
HTTPS auth.
|
HTTPS auth.
|
||||||
|
- `bin/` — installs userland CLI tools (ripgrep, fd, bat, fzf, jq) as
|
||||||
|
self-contained release binaries into `~/.local/bin`. No sudo, nothing
|
||||||
|
outside `$HOME`, so they persist across Kasm redeploys with no reinstall.
|
||||||
|
Idempotent: pinned versions already present are skipped. `zsh/zshrc` puts
|
||||||
|
`~/.local/bin` on `PATH`.
|
||||||
- `mcp-config/` — shared MCP gateway config sync for laptops (LiteLLM /
|
- `mcp-config/` — shared MCP gateway config sync for laptops (LiteLLM /
|
||||||
opencode). Independent of `bootstrap.sh`; see its own README.
|
opencode). Independent of `bootstrap.sh`; see its own README.
|
||||||
|
|
||||||
`lib/os-detect.sh` provides shared package-manager detection (`dnf`/`yum`
|
`lib/os-detect.sh` provides shared package-manager detection (`dnf`/`yum`
|
||||||
vs `apt`) used by module install scripts.
|
vs `apt`); `lib/fetch.sh` provides arch detection and binary-download
|
||||||
|
helpers. Both are used by module install scripts.
|
||||||
|
|||||||
Executable
+83
@@ -0,0 +1,83 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# bin/install.sh — install userland CLI tools into ~/.local/bin.
|
||||||
|
#
|
||||||
|
# Every tool is a self-contained release binary downloaded from upstream and
|
||||||
|
# dropped into ~/.local/bin (no sudo, nothing outside $HOME), so it persists
|
||||||
|
# across Kasm redeploys. Idempotent: each tool is skipped when the pinned
|
||||||
|
# version is already installed. To add a tool, pin a version, add an
|
||||||
|
# install_<name> function, and call it at the bottom.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||||
|
REPO_ROOT="$(dirname -- "$SCRIPT_DIR")"
|
||||||
|
|
||||||
|
# shellcheck source=../lib/fetch.sh
|
||||||
|
. "$REPO_ROOT/lib/fetch.sh"
|
||||||
|
|
||||||
|
ARCH="$(fetch_arch)"
|
||||||
|
|
||||||
|
# ripgrep — fast recursive search. x86_64 ships musl (static); aarch64 gnu.
|
||||||
|
install_ripgrep() {
|
||||||
|
ver=15.1.0
|
||||||
|
have_version rg "$ver" && { fsay "ripgrep $ver already installed."; return 0; }
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) triple=x86_64-unknown-linux-musl ;;
|
||||||
|
aarch64) triple=aarch64-unknown-linux-gnu ;;
|
||||||
|
esac
|
||||||
|
install_tarball_bin \
|
||||||
|
"https://github.com/BurntSushi/ripgrep/releases/download/$ver/ripgrep-$ver-$triple.tar.gz" \
|
||||||
|
"ripgrep-$ver-$triple/rg" rg
|
||||||
|
}
|
||||||
|
|
||||||
|
# fd — fast, user-friendly find. musl (static) on both arches.
|
||||||
|
install_fd() {
|
||||||
|
ver=10.4.2
|
||||||
|
have_version fd "$ver" && { fsay "fd $ver already installed."; return 0; }
|
||||||
|
triple="$ARCH-unknown-linux-musl"
|
||||||
|
install_tarball_bin \
|
||||||
|
"https://github.com/sharkdp/fd/releases/download/v$ver/fd-v$ver-$triple.tar.gz" \
|
||||||
|
"fd-v$ver-$triple/fd" fd
|
||||||
|
}
|
||||||
|
|
||||||
|
# bat — cat with syntax highlighting. musl (static) on both arches.
|
||||||
|
install_bat() {
|
||||||
|
ver=0.26.1
|
||||||
|
have_version bat "$ver" && { fsay "bat $ver already installed."; return 0; }
|
||||||
|
triple="$ARCH-unknown-linux-musl"
|
||||||
|
install_tarball_bin \
|
||||||
|
"https://github.com/sharkdp/bat/releases/download/v$ver/bat-v$ver-$triple.tar.gz" \
|
||||||
|
"bat-v$ver-$triple/bat" bat
|
||||||
|
}
|
||||||
|
|
||||||
|
# fzf — general-purpose fuzzy finder (static Go binary).
|
||||||
|
install_fzf() {
|
||||||
|
ver=0.74.0
|
||||||
|
have_version fzf "$ver" && { fsay "fzf $ver already installed."; return 0; }
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) a=amd64 ;;
|
||||||
|
aarch64) a=arm64 ;;
|
||||||
|
esac
|
||||||
|
install_tarball_bin \
|
||||||
|
"https://github.com/junegunn/fzf/releases/download/v$ver/fzf-$ver-linux_$a.tar.gz" \
|
||||||
|
fzf fzf
|
||||||
|
}
|
||||||
|
|
||||||
|
# jq — command-line JSON processor (single static binary).
|
||||||
|
install_jq() {
|
||||||
|
ver=1.8.2
|
||||||
|
have_version jq "$ver" && { fsay "jq $ver already installed."; return 0; }
|
||||||
|
case "$ARCH" in
|
||||||
|
x86_64) a=amd64 ;;
|
||||||
|
aarch64) a=arm64 ;;
|
||||||
|
esac
|
||||||
|
install_raw_bin \
|
||||||
|
"https://github.com/jqlang/jq/releases/download/jq-$ver/jq-linux-$a" jq
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ripgrep
|
||||||
|
install_fd
|
||||||
|
install_bat
|
||||||
|
install_fzf
|
||||||
|
install_jq
|
||||||
|
|
||||||
|
fsay "Done. Tools in $BIN_DIR (added to PATH by zsh/zshrc)."
|
||||||
@@ -31,3 +31,4 @@ fi
|
|||||||
|
|
||||||
"$SCRIPT_DIR/zsh/install.sh"
|
"$SCRIPT_DIR/zsh/install.sh"
|
||||||
"$SCRIPT_DIR/git/install.sh"
|
"$SCRIPT_DIR/git/install.sh"
|
||||||
|
"$SCRIPT_DIR/bin/install.sh"
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# lib/fetch.sh — helpers for installing userland binaries into ~/.local/bin.
|
||||||
|
#
|
||||||
|
# Everything lands under $HOME, so installed tools survive Kasm redeploys
|
||||||
|
# (which wipe the root filesystem but keep $HOME) with no reinstall needed.
|
||||||
|
# No sudo, no system packages. Prefer statically linked (musl) release
|
||||||
|
# binaries so they keep working even after the root fs — and its shared
|
||||||
|
# libraries — is reset.
|
||||||
|
#
|
||||||
|
# Source this (callers already run `set -eu`), then use fetch_arch,
|
||||||
|
# have_version, install_tarball_bin, and install_raw_bin.
|
||||||
|
|
||||||
|
BIN_DIR="${BIN_DIR:-$HOME/.local/bin}"
|
||||||
|
|
||||||
|
fsay() { printf '%s\n' "$*" >&2; }
|
||||||
|
|
||||||
|
# Normalize `uname -m` to the canonical arch tokens used below.
|
||||||
|
fetch_arch() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) printf 'x86_64\n' ;;
|
||||||
|
aarch64|arm64) printf 'aarch64\n' ;;
|
||||||
|
*) fsay "fetch: unsupported arch $(uname -m)"; return 1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download <url> to <dest-file> using whatever downloader is available.
|
||||||
|
_fetch_dl() {
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
curl -fsSL "$1" -o "$2"
|
||||||
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
|
wget -qO "$2" "$1"
|
||||||
|
else
|
||||||
|
fsay "fetch: need curl or wget"; return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# have_version <cmd> <version-substring> — true if ~/.local/bin/<cmd> exists
|
||||||
|
# and reports the given version, so bootstrap can skip a re-download.
|
||||||
|
have_version() {
|
||||||
|
_bin="$BIN_DIR/$1"
|
||||||
|
[ -x "$_bin" ] || return 1
|
||||||
|
"$_bin" --version 2>/dev/null | grep -qF "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# install_tarball_bin <url> <path-within-archive> <dest-name> — download a
|
||||||
|
# .tar.gz, extract, and install one binary from it into ~/.local/bin.
|
||||||
|
install_tarball_bin() {
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
_tmp="$(mktemp -d)"
|
||||||
|
_fetch_dl "$1" "$_tmp/archive.tar.gz"
|
||||||
|
tar -xzf "$_tmp/archive.tar.gz" -C "$_tmp"
|
||||||
|
install -m 0755 "$_tmp/$2" "$BIN_DIR/$3"
|
||||||
|
rm -rf "$_tmp"
|
||||||
|
fsay "installed $BIN_DIR/$3"
|
||||||
|
}
|
||||||
|
|
||||||
|
# install_raw_bin <url> <dest-name> — download a single raw binary.
|
||||||
|
install_raw_bin() {
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
_tmp="$(mktemp)"
|
||||||
|
_fetch_dl "$1" "$_tmp"
|
||||||
|
install -m 0755 "$_tmp" "$BIN_DIR/$2"
|
||||||
|
rm -f "$_tmp"
|
||||||
|
fsay "installed $BIN_DIR/$2"
|
||||||
|
}
|
||||||
@@ -2,6 +2,12 @@
|
|||||||
# overwritten on the next bootstrap run. Edit zsh/zshrc in the dotfiles repo
|
# overwritten on the next bootstrap run. Edit zsh/zshrc in the dotfiles repo
|
||||||
# instead.
|
# instead.
|
||||||
|
|
||||||
|
# Userland tools installed by dotfiles/bin/install.sh live here.
|
||||||
|
case ":$PATH:" in
|
||||||
|
*":$HOME/.local/bin:"*) ;;
|
||||||
|
*) export PATH="$HOME/.local/bin:$PATH" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
export ZSH="$HOME/.oh-my-zsh"
|
export ZSH="$HOME/.oh-my-zsh"
|
||||||
|
|
||||||
ZSH_THEME="robbyrussell"
|
ZSH_THEME="robbyrussell"
|
||||||
|
|||||||
Reference in New Issue
Block a user