Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# sherlock installer.
|
||||
#
|
||||
# Run from a clone of this repo:
|
||||
#
|
||||
# ./install.sh
|
||||
#
|
||||
# It:
|
||||
# 1. copies config.example.toml to your sherlock config path
|
||||
# (default ~/.config/sherlock/config.toml) if you don't have one yet,
|
||||
# 2. opens it in your editor so you can fill in your deployment values,
|
||||
# 3. on save, `go install`s sherlock and every MCP binary.
|
||||
#
|
||||
# Flags:
|
||||
# -y, --yes skip the editor step (config is already filled in)
|
||||
# --config-only set up/edit the config but do NOT build/install
|
||||
# -h, --help show this help
|
||||
#
|
||||
# Env overrides:
|
||||
# SHERLOCK_CONFIG exact config path to write (else XDG / ~/.config)
|
||||
# VISUAL / EDITOR editor to open (falls back to nano, then vi)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
EXAMPLE="$SCRIPT_DIR/config.example.toml"
|
||||
|
||||
# Every cmd/<dir> that ships a binary. Keep in sync with cmd/.
|
||||
BINARIES=(sherlock gitea-mcp grafana-mcp gssh-mcp)
|
||||
|
||||
SKIP_EDITOR=0
|
||||
CONFIG_ONLY=0
|
||||
|
||||
info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33mwarning:\033[0m %s\n' "$*" >&2; }
|
||||
die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
usage() {
|
||||
sed -n '3,25p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
|
||||
exit "${1:-0}"
|
||||
}
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-y|--yes) SKIP_EDITOR=1 ;;
|
||||
--config-only) CONFIG_ONLY=1 ;;
|
||||
-h|--help) usage 0 ;;
|
||||
*) warn "unknown argument: $1"; usage 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# ── Resolve the config path (mirrors internal/config.DefaultPath) ─────
|
||||
config_path() {
|
||||
if [ -n "${SHERLOCK_CONFIG:-}" ]; then
|
||||
printf '%s\n' "$SHERLOCK_CONFIG"
|
||||
elif [ -n "${XDG_CONFIG_HOME:-}" ]; then
|
||||
printf '%s/sherlock/config.toml\n' "$XDG_CONFIG_HOME"
|
||||
else
|
||||
printf '%s/.config/sherlock/config.toml\n' "$HOME"
|
||||
fi
|
||||
}
|
||||
|
||||
CONFIG="$(config_path)"
|
||||
|
||||
# ── 1. Seed the config from the example (never clobber a filled one) ──
|
||||
[ -f "$EXAMPLE" ] || die "config.example.toml not found next to this script ($EXAMPLE). Run install.sh from inside the repo."
|
||||
|
||||
if [ -f "$CONFIG" ]; then
|
||||
info "Existing config found at $CONFIG — editing it in place (not overwriting)."
|
||||
else
|
||||
info "Creating $CONFIG from config.example.toml"
|
||||
mkdir -p "$(dirname "$CONFIG")"
|
||||
cp "$EXAMPLE" "$CONFIG"
|
||||
chmod 600 "$CONFIG"
|
||||
fi
|
||||
|
||||
# ── 2. Open it in the editor and wait for the user to finish ─────────
|
||||
pick_editor() {
|
||||
if [ -n "${VISUAL:-}" ]; then printf '%s\n' "$VISUAL"; return; fi
|
||||
if [ -n "${EDITOR:-}" ]; then printf '%s\n' "$EDITOR"; return; fi
|
||||
for e in sensible-editor nano vi; do
|
||||
if command -v "$e" >/dev/null 2>&1; then printf '%s\n' "$e"; return; fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ "$SKIP_EDITOR" -eq 0 ]; then
|
||||
if EDITOR_CMD="$(pick_editor)"; then
|
||||
info "Opening $CONFIG in: $EDITOR_CMD"
|
||||
# shellcheck disable=SC2086
|
||||
$EDITOR_CMD "$CONFIG"
|
||||
else
|
||||
warn "No editor found (set \$EDITOR). Edit $CONFIG by hand, then re-run with -y."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Light sanity check: warn (don't block) on leftover placeholders.
|
||||
if grep -q 'REPLACE_' "$CONFIG" 2>/dev/null; then
|
||||
warn "$CONFIG still contains REPLACE_… placeholders — fill them in before using sherlock."
|
||||
fi
|
||||
|
||||
if [ "$CONFIG_ONLY" -eq 1 ]; then
|
||||
info "Config ready at $CONFIG (skipping install: --config-only)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── 3. Build + install every binary from this clone ──────────────────
|
||||
command -v go >/dev/null 2>&1 || die "the Go toolchain is required but 'go' was not found on PATH. Install Go, then re-run."
|
||||
|
||||
info "Installing binaries: ${BINARIES[*]}"
|
||||
pkgs=()
|
||||
for b in "${BINARIES[@]}"; do
|
||||
pkgs+=("./cmd/$b")
|
||||
done
|
||||
( cd "$SCRIPT_DIR" && go install "${pkgs[@]}" )
|
||||
|
||||
# ── 4. Report where they landed and whether that's on PATH ───────────
|
||||
bindir="$(go env GOBIN)"
|
||||
[ -n "$bindir" ] || bindir="$(go env GOPATH)/bin"
|
||||
info "Installed to $bindir"
|
||||
|
||||
case ":$PATH:" in
|
||||
*":$bindir:"*) : ;;
|
||||
*) warn "$bindir is not on your \$PATH. Add it, e.g.:
|
||||
echo 'export PATH=\"$bindir:\$PATH\"' >> ~/.bashrc && source ~/.bashrc" ;;
|
||||
esac
|
||||
|
||||
info "Done. Try: sherlock copilot"
|
||||
Reference in New Issue
Block a user