install.sh 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #!/bin/sh
  2. # Roo Code CLI Installer
  3. # Usage: curl -fsSL https://raw.githubusercontent.com/RooCodeInc/Roo-Code/main/apps/cli/install.sh | sh
  4. #
  5. # Environment variables:
  6. # ROO_INSTALL_DIR - Installation directory (default: ~/.roo/cli)
  7. # ROO_BIN_DIR - Binary symlink directory (default: ~/.local/bin)
  8. # ROO_VERSION - Specific version to install (default: latest)
  9. # ROO_LOCAL_TARBALL - Path to local tarball to install (skips download)
  10. set -e
  11. # Configuration
  12. INSTALL_DIR="${ROO_INSTALL_DIR:-$HOME/.roo/cli}"
  13. BIN_DIR="${ROO_BIN_DIR:-$HOME/.local/bin}"
  14. REPO="RooCodeInc/Roo-Code"
  15. MIN_NODE_VERSION=20
  16. # Color output (only if terminal supports it)
  17. if [ -t 1 ]; then
  18. RED='\033[0;31m'
  19. GREEN='\033[0;32m'
  20. YELLOW='\033[1;33m'
  21. BLUE='\033[0;34m'
  22. BOLD='\033[1m'
  23. NC='\033[0m'
  24. else
  25. RED=''
  26. GREEN=''
  27. YELLOW=''
  28. BLUE=''
  29. BOLD=''
  30. NC=''
  31. fi
  32. info() { printf "${GREEN}==>${NC} %s\n" "$1"; }
  33. warn() { printf "${YELLOW}Warning:${NC} %s\n" "$1"; }
  34. error() { printf "${RED}Error:${NC} %s\n" "$1" >&2; exit 1; }
  35. # Check Node.js version
  36. check_node() {
  37. if ! command -v node >/dev/null 2>&1; then
  38. error "Node.js is not installed. Please install Node.js $MIN_NODE_VERSION or higher.
  39. Install Node.js:
  40. - macOS: brew install node
  41. - Linux: https://nodejs.org/en/download/package-manager
  42. - Or use a version manager like fnm, nvm, or mise"
  43. fi
  44. NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
  45. if [ "$NODE_VERSION" -lt "$MIN_NODE_VERSION" ]; then
  46. error "Node.js $MIN_NODE_VERSION+ required. Found: $(node -v)
  47. Please upgrade Node.js to version $MIN_NODE_VERSION or higher."
  48. fi
  49. info "Found Node.js $(node -v)"
  50. }
  51. # Detect OS and architecture
  52. detect_platform() {
  53. OS=$(uname -s | tr '[:upper:]' '[:lower:]')
  54. ARCH=$(uname -m)
  55. case "$OS" in
  56. darwin) OS="darwin" ;;
  57. linux) OS="linux" ;;
  58. mingw*|msys*|cygwin*)
  59. error "Windows is not supported by this installer. Please use WSL or install manually."
  60. ;;
  61. *) error "Unsupported OS: $OS" ;;
  62. esac
  63. case "$ARCH" in
  64. x86_64|amd64) ARCH="x64" ;;
  65. arm64|aarch64) ARCH="arm64" ;;
  66. *) error "Unsupported architecture: $ARCH" ;;
  67. esac
  68. PLATFORM="${OS}-${ARCH}"
  69. info "Detected platform: $PLATFORM"
  70. }
  71. # Get latest release version or use specified version
  72. get_version() {
  73. # Skip version fetch if using local tarball
  74. if [ -n "$ROO_LOCAL_TARBALL" ]; then
  75. VERSION="${ROO_VERSION:-local}"
  76. info "Using local tarball (version: $VERSION)"
  77. return
  78. fi
  79. if [ -n "$ROO_VERSION" ]; then
  80. VERSION="$ROO_VERSION"
  81. info "Using specified version: $VERSION"
  82. return
  83. fi
  84. info "Fetching latest version..."
  85. # Try to get the latest cli release
  86. RELEASES_JSON=$(curl -fsSL "https://api.github.com/repos/$REPO/releases" 2>/dev/null) || {
  87. error "Failed to fetch releases from GitHub. Check your internet connection."
  88. }
  89. # Extract the latest cli-v* tag
  90. VERSION=$(echo "$RELEASES_JSON" |
  91. grep -o '"tag_name": "cli-v[^"]*"' |
  92. head -1 |
  93. sed 's/"tag_name": "cli-v//' |
  94. sed 's/"//')
  95. if [ -z "$VERSION" ]; then
  96. error "Could not find any CLI releases. The CLI may not have been released yet."
  97. fi
  98. info "Latest version: $VERSION"
  99. }
  100. # Download and extract
  101. download_and_install() {
  102. TARBALL="roo-cli-${PLATFORM}.tar.gz"
  103. # Create temp directory
  104. TMP_DIR=$(mktemp -d)
  105. trap "rm -rf $TMP_DIR" EXIT
  106. # Use local tarball if provided, otherwise download
  107. if [ -n "$ROO_LOCAL_TARBALL" ]; then
  108. if [ ! -f "$ROO_LOCAL_TARBALL" ]; then
  109. error "Local tarball not found: $ROO_LOCAL_TARBALL"
  110. fi
  111. info "Using local tarball: $ROO_LOCAL_TARBALL"
  112. cp "$ROO_LOCAL_TARBALL" "$TMP_DIR/$TARBALL"
  113. else
  114. URL="https://github.com/$REPO/releases/download/cli-v${VERSION}/${TARBALL}"
  115. info "Downloading from $URL..."
  116. # Download with progress indicator
  117. HTTP_CODE=$(curl -fsSL -w "%{http_code}" "$URL" -o "$TMP_DIR/$TARBALL" 2>/dev/null) || {
  118. if [ "$HTTP_CODE" = "404" ]; then
  119. error "Release not found for platform $PLATFORM version $VERSION.
  120. Available at: https://github.com/$REPO/releases"
  121. fi
  122. error "Download failed. HTTP code: $HTTP_CODE"
  123. }
  124. # Verify we got something
  125. if [ ! -s "$TMP_DIR/$TARBALL" ]; then
  126. error "Downloaded file is empty. Please try again."
  127. fi
  128. fi
  129. # Remove old installation if exists
  130. if [ -d "$INSTALL_DIR" ]; then
  131. info "Removing previous installation..."
  132. rm -rf "$INSTALL_DIR"
  133. fi
  134. mkdir -p "$INSTALL_DIR"
  135. # Extract
  136. info "Extracting to $INSTALL_DIR..."
  137. tar -xzf "$TMP_DIR/$TARBALL" -C "$INSTALL_DIR" --strip-components=1 || {
  138. error "Failed to extract tarball. The download may be corrupted."
  139. }
  140. # Save ripgrep binary before npm install (npm install will overwrite node_modules)
  141. RIPGREP_BIN=""
  142. if [ -f "$INSTALL_DIR/node_modules/@vscode/ripgrep/bin/rg" ]; then
  143. RIPGREP_BIN="$TMP_DIR/rg"
  144. cp "$INSTALL_DIR/node_modules/@vscode/ripgrep/bin/rg" "$RIPGREP_BIN"
  145. fi
  146. # Install npm dependencies
  147. info "Installing dependencies..."
  148. cd "$INSTALL_DIR"
  149. npm install --production --silent 2>/dev/null || {
  150. warn "npm install failed, trying with --legacy-peer-deps..."
  151. npm install --production --legacy-peer-deps --silent 2>/dev/null || {
  152. error "Failed to install dependencies. Make sure npm is available."
  153. }
  154. }
  155. cd - > /dev/null
  156. # Restore ripgrep binary after npm install
  157. if [ -n "$RIPGREP_BIN" ] && [ -f "$RIPGREP_BIN" ]; then
  158. mkdir -p "$INSTALL_DIR/node_modules/@vscode/ripgrep/bin"
  159. cp "$RIPGREP_BIN" "$INSTALL_DIR/node_modules/@vscode/ripgrep/bin/rg"
  160. chmod +x "$INSTALL_DIR/node_modules/@vscode/ripgrep/bin/rg"
  161. fi
  162. # Make executable
  163. chmod +x "$INSTALL_DIR/bin/roo"
  164. # Also make ripgrep executable if it exists
  165. if [ -f "$INSTALL_DIR/bin/rg" ]; then
  166. chmod +x "$INSTALL_DIR/bin/rg"
  167. fi
  168. }
  169. # Create symlink in bin directory
  170. setup_bin() {
  171. mkdir -p "$BIN_DIR"
  172. # Remove old symlink if exists
  173. if [ -L "$BIN_DIR/roo" ] || [ -f "$BIN_DIR/roo" ]; then
  174. rm -f "$BIN_DIR/roo"
  175. fi
  176. ln -sf "$INSTALL_DIR/bin/roo" "$BIN_DIR/roo"
  177. info "Created symlink: $BIN_DIR/roo"
  178. }
  179. # Check if bin dir is in PATH and provide instructions
  180. check_path() {
  181. case ":$PATH:" in
  182. *":$BIN_DIR:"*)
  183. # Already in PATH
  184. return 0
  185. ;;
  186. esac
  187. warn "$BIN_DIR is not in your PATH"
  188. echo ""
  189. echo "Add this line to your shell profile:"
  190. echo ""
  191. # Detect shell and provide specific instructions
  192. SHELL_NAME=$(basename "$SHELL")
  193. case "$SHELL_NAME" in
  194. zsh)
  195. echo " echo 'export PATH=\"$BIN_DIR:\$PATH\"' >> ~/.zshrc"
  196. echo " source ~/.zshrc"
  197. ;;
  198. bash)
  199. if [ -f "$HOME/.bashrc" ]; then
  200. echo " echo 'export PATH=\"$BIN_DIR:\$PATH\"' >> ~/.bashrc"
  201. echo " source ~/.bashrc"
  202. else
  203. echo " echo 'export PATH=\"$BIN_DIR:\$PATH\"' >> ~/.bash_profile"
  204. echo " source ~/.bash_profile"
  205. fi
  206. ;;
  207. fish)
  208. echo " set -Ux fish_user_paths $BIN_DIR \$fish_user_paths"
  209. ;;
  210. *)
  211. echo " export PATH=\"$BIN_DIR:\$PATH\""
  212. ;;
  213. esac
  214. echo ""
  215. }
  216. # Verify installation
  217. verify_install() {
  218. if [ -x "$BIN_DIR/roo" ]; then
  219. info "Verifying installation..."
  220. # Just check if it runs without error
  221. "$BIN_DIR/roo" --version >/dev/null 2>&1 || true
  222. fi
  223. }
  224. # Print success message
  225. print_success() {
  226. echo ""
  227. printf "${GREEN}${BOLD}✓ Roo Code CLI installed successfully!${NC}\n"
  228. echo ""
  229. echo " Installation: $INSTALL_DIR"
  230. echo " Binary: $BIN_DIR/roo"
  231. echo " Version: $VERSION"
  232. echo ""
  233. echo " ${BOLD}Get started:${NC}"
  234. echo " roo --help"
  235. echo ""
  236. echo " ${BOLD}Example:${NC}"
  237. echo " export OPENROUTER_API_KEY=sk-or-v1-..."
  238. echo " roo ~/my-project -P \"What is this project?\""
  239. echo ""
  240. }
  241. # Main
  242. main() {
  243. echo ""
  244. printf "${BLUE}${BOLD}"
  245. echo " ╭─────────────────────────────────╮"
  246. echo " │ Roo Code CLI Installer │"
  247. echo " ╰─────────────────────────────────╯"
  248. printf "${NC}"
  249. echo ""
  250. check_node
  251. detect_platform
  252. get_version
  253. download_and_install
  254. setup_bin
  255. check_path
  256. verify_install
  257. print_success
  258. }
  259. main "$@"