-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·193 lines (158 loc) · 5.48 KB
/
install.sh
File metadata and controls
executable file
·193 lines (158 loc) · 5.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#!/bin/sh
# Unsupervised CLI installer
# Usage: curl -fsSL https://unsupervised.com/cli/install.sh | sh
#
# Environment variables:
# UNSUPERVISED_VERSION — version to install (default: latest)
# UNSUPERVISED_INSTALL_DIR — install directory (default: ~/.local/bin)
set -eu
if [ -z "${HOME:-}" ]; then
printf 'error: $HOME is not set — cannot determine install directory\n' >&2
exit 1
fi
INSTALL_DIR="${UNSUPERVISED_INSTALL_DIR:-$HOME/.local/bin}"
REPO="Unsupervisedcom/unsupervised_cli"
GITHUB_BASE="https://github.com/${REPO}/releases"
# --- helpers ----------------------------------------------------------------
LOG_PREFIX=""
ERR_PREFIX=""
WARN_PREFIX=""
COLOR_RESET=""
if [ -z "${NO_COLOR:-}" ]; then
if [ -t 1 ]; then
LOG_PREFIX="$(printf '\033[1;34m')"
WARN_PREFIX="$(printf '\033[1;33m')"
COLOR_RESET="$(printf '\033[0m')"
fi
if [ -t 2 ]; then
ERR_PREFIX="$(printf '\033[1;31m')"
[ -n "$COLOR_RESET" ] || COLOR_RESET="$(printf '\033[0m')"
fi
fi
log() { printf '%s%s%s\n' "$LOG_PREFIX" "$*" "$COLOR_RESET"; }
warn() { printf '%swarning: %s%s\n' "$WARN_PREFIX" "$*" "$COLOR_RESET" >&2; }
err() { printf '%serror: %s%s\n' "$ERR_PREFIX" "$*" "$COLOR_RESET" >&2; exit 1; }
detect_platform() {
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
Linux*) OS="linux" ;;
Darwin*) OS="darwin" ;;
*) err "Unsupported OS: $OS" ;;
esac
case "$ARCH" in
x86_64|amd64) ARCH="x64" ;;
aarch64|arm64) ARCH="arm64" ;;
*) err "Unsupported architecture: $ARCH" ;;
esac
}
check_root() {
if [ "$(id -u)" = "0" ]; then
case "$INSTALL_DIR" in
"$HOME"*|/root*)
warn "Running as root — installing to '${INSTALL_DIR}' will create root-owned files in a user directory."
warn "Consider using UNSUPERVISED_INSTALL_DIR=/usr/local/bin instead."
;;
esac
fi
}
PATH_LINE="export PATH=\"${INSTALL_DIR}:\$PATH\""
add_to_profile() {
profile="$1"
[ -f "$profile" ] || return 1
# Already present
grep -qF "$PATH_LINE" "$profile" 2>/dev/null && return 1
printf '\n# Added by Unsupervised CLI installer\n%s\n' "$PATH_LINE" >> "$profile"
return 0
}
ensure_in_path() {
case ":${PATH:-}:" in
*":${INSTALL_DIR}:"*) return ;;
esac
UPDATED_FILES=""
FIRST_FILE=""
for profile in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile" "$HOME/.bash_profile"; do
if add_to_profile "$profile"; then
UPDATED_FILES="${UPDATED_FILES} ${profile}"
[ -z "$FIRST_FILE" ] && FIRST_FILE="$profile"
fi
done
if [ -n "$UPDATED_FILES" ]; then
log ""
log "Added ${INSTALL_DIR} to PATH in:${UPDATED_FILES}"
log ""
log "Restart your shell or run: source ${FIRST_FILE}"
else
log ""
log "Add the install directory to your PATH:"
log ""
log " ${PATH_LINE}"
log ""
log "Or add it to your shell profile (~/.bashrc, ~/.zshrc, etc.)."
fi
}
ensure_claude_code() {
if command -v claude >/dev/null 2>&1; then
log "Claude Code is already installed ($(claude --version 2>/dev/null || echo 'unknown version'))."
return
fi
log ""
log "Claude Code is not installed — installing via the official installer..."
if ! curl -fsSL https://claude.ai/install.sh | bash; then
warn "Claude Code installation failed. Install it manually: https://docs.anthropic.com/en/docs/claude-code/setup"
warn "Unsupervised CLI was installed successfully but requires Claude Code to run."
return
fi
log "Claude Code installed successfully."
}
ensure_uvx() {
if command -v uvx >/dev/null 2>&1; then
log "uvx is already installed ($(uvx --version 2>/dev/null || echo 'unknown version'))."
return
fi
log ""
log "uvx is not installed — installing uv via the official installer..."
if ! curl -LsSf https://astral.sh/uv/install.sh | sh; then
warn "uv installation failed. Install it manually: https://docs.astral.sh/uv/getting-started/installation/"
warn "Unsupervised CLI was installed successfully but requires uvx to run."
return
fi
log "uv (includes uvx) installed successfully."
}
# --- main -------------------------------------------------------------------
main() {
detect_platform
check_root
BINARY="unsupervised-${OS}-${ARCH}"
# Resolve version: explicit env var, or latest release tag
if [ -n "${UNSUPERVISED_VERSION:-}" ]; then
VERSION="${UNSUPERVISED_VERSION#v}"
TAG="v${VERSION}"
else
TAG="$(curl -fsSI "${GITHUB_BASE}/latest" 2>/dev/null | grep -i '^location:' | sed 's|.*/||' | tr -d '\r\n')"
if [ -z "$TAG" ] || [ "$TAG" = "latest" ]; then
err "Could not determine latest release. Set UNSUPERVISED_VERSION explicitly."
fi
VERSION="${TAG#v}"
fi
DOWNLOAD_URL="${GITHUB_BASE}/download/${TAG}/${BINARY}"
log "Installing unsupervised v${VERSION} (${OS}/${ARCH})..."
mkdir -p "$INSTALL_DIR"
TMPDIR_WORK="$(mktemp -d "${TMPDIR:-/tmp}/unsupervised.XXXXXX")"
trap 'rm -rf "$TMPDIR_WORK"' EXIT
log "Downloading ${BINARY} from release ${TAG}..."
if ! curl -fSL --progress-bar -o "${TMPDIR_WORK}/${BINARY}" "$DOWNLOAD_URL"; then
err "Download failed. Check that release ${TAG} exists at ${GITHUB_BASE}"
fi
mv "${TMPDIR_WORK}/${BINARY}" "${INSTALL_DIR}/unsupervised"
chmod +x "${INSTALL_DIR}/unsupervised"
log "Installed to ${INSTALL_DIR}/unsupervised"
# Ensure INSTALL_DIR is in PATH for future sessions
ensure_in_path
# Claude Code and uvx are required to run Unsupervised — install if missing
ensure_claude_code
ensure_uvx
log ""
log "Run 'unsupervised --help' to get started."
}
main