#!/usr/bin/env bashset -euo pipefailAPP=opencodeMUTED='033円[0;2m'RED='033円[0;31m'ORANGE='033円[38;5;214m'NC='033円[0m' # No Colorusage() {cat <<EOFOpenCode InstallerUsage: install.sh [options]Options:-h, --help Display this help message-v, --version <version> Install a specific version (e.g., 1.0.180)-b, --binary <path> Install from a local binary instead of downloading--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)Examples:curl -fsSL https://opencode.ai/install | bashcurl -fsSL https://opencode.ai/install | bash -s -- --version 1.0.180./install --binary /path/to/opencodeEOF}requested_version=${VERSION:-}no_modify_path=falsebinary_path=""while [[ $# -gt 0 ]]; docase "1ドル" in-h|--help)usageexit 0;;-v|--version)if [[ -n "${2:-}" ]]; thenrequested_version="2ドル"shift 2elseecho -e "${RED}Error: --version requires a version argument${NC}"exit 1fi;;-b|--binary)if [[ -n "${2:-}" ]]; thenbinary_path="2ドル"shift 2elseecho -e "${RED}Error: --binary requires a path argument${NC}"exit 1fi;;--no-modify-path)no_modify_path=trueshift;;*)echo -e "${ORANGE}Warning: Unknown option '1ドル'${NC}" >&2shift;;esacdoneINSTALL_DIR=$HOME/.opencode/binmkdir -p "$INSTALL_DIR"# If --binary is provided, skip all download/detection logicif [ -n "$binary_path" ]; thenif [ ! -f "$binary_path" ]; thenecho -e "${RED}Error: Binary not found at ${binary_path}${NC}"exit 1fispecific_version="local"elseraw_os=$(uname -s)os=$(echo "$raw_os" | tr '[:upper:]' '[:lower:]')case "$raw_os" inDarwin*) os="darwin" ;;Linux*) os="linux" ;;MINGW*|MSYS*|CYGWIN*) os="windows" ;;esacarch=$(uname -m)if [[ "$arch" == "aarch64" ]]; thenarch="arm64"fiif [[ "$arch" == "x86_64" ]]; thenarch="x64"fiif [ "$os" = "darwin" ] && [ "$arch" = "x64" ]; thenrosetta_flag=$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)if [ "$rosetta_flag" = "1" ]; thenarch="arm64"fificombo="$os-$arch"case "$combo" inlinux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64);;*)echo -e "${RED}Unsupported OS/Arch: $os/$arch${NC}"exit 1;;esacarchive_ext=".zip"if [ "$os" = "linux" ]; thenarchive_ext=".tar.gz"fiis_musl=falseif [ "$os" = "linux" ]; thenif [ -f /etc/alpine-release ]; thenis_musl=truefiif command -v ldd >/dev/null 2>&1; thenif ldd --version 2>&1 | grep -qi musl; thenis_musl=truefififineeds_baseline=falseif [ "$arch" = "x64" ]; thenif [ "$os" = "linux" ]; thenif ! grep -qwi avx2 /proc/cpuinfo 2>/dev/null; thenneeds_baseline=truefifiif [ "$os" = "darwin" ]; thenavx2=$(sysctl -n hw.optional.avx2_0 2>/dev/null || echo 0)if [ "$avx2" != "1" ]; thenneeds_baseline=truefifiif [ "$os" = "windows" ]; thenps="(Add-Type -MemberDefinition \"[DllImport(\"\"kernel32.dll\"\")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);\" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)"out=""if command -v powershell.exe >/dev/null 2>&1; thenout=$(powershell.exe -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)elif command -v pwsh >/dev/null 2>&1; thenout=$(pwsh -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)fiout=$(echo "$out" | tr -d '\r' | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')if [ "$out" != "true" ] && [ "$out" != "1" ]; thenneeds_baseline=truefififitarget="$os-$arch"if [ "$needs_baseline" = "true" ]; thentarget="$target-baseline"fiif [ "$is_musl" = "true" ]; thentarget="$target-musl"fifilename="$APP-$target$archive_ext"if [ "$os" = "linux" ]; thenif ! command -v tar >/dev/null 2>&1; thenecho -e "${RED}Error: 'tar' is required but not installed.${NC}"exit 1fielseif ! command -v unzip >/dev/null 2>&1; thenecho -e "${RED}Error: 'unzip' is required but not installed.${NC}"exit 1fifiif [ -z "$requested_version" ]; thenurl="https://github.com/anomalyco/opencode/releases/latest/download/$filename"specific_version=$(curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/1円/p')if [[ $? -ne 0 || -z "$specific_version" ]]; thenecho -e "${RED}Failed to fetch version information${NC}"exit 1fielse# Strip leading 'v' if presentrequested_version="${requested_version#v}"url="https://github.com/anomalyco/opencode/releases/download/v${requested_version}/$filename"specific_version=$requested_version# Verify the release exists before downloadinghttp_status=$(curl -sI -o /dev/null -w "%{http_code}" "https://github.com/anomalyco/opencode/releases/tag/v${requested_version}")if [ "$http_status" = "404" ]; thenecho -e "${RED}Error: Release v${requested_version} not found${NC}"echo -e "${MUTED}Available releases: https://github.com/anomalyco/opencode/releases${NC}"exit 1fififiprint_message() {local level=1ドルlocal message=2ドルlocal color=""case $level ininfo) color="${NC}" ;;warning) color="${NC}" ;;error) color="${RED}" ;;esacecho -e "${color}${message}${NC}"}check_version() {if command -v opencode >/dev/null 2>&1; thenopencode_path=$(which opencode)## Check the installed versioninstalled_version=$(opencode --version 2>/dev/null || echo "")if [[ "$installed_version" != "$specific_version" ]]; thenprint_message info "${MUTED}Installed version: ${NC}$installed_version."elseprint_message info "${MUTED}Version ${NC}$specific_version${MUTED} already installed"exit 0fifi}unbuffered_sed() {if echo | sed -u -e "" >/dev/null 2>&1; thensed -nu "$@"elif echo | sed -l -e "" >/dev/null 2>&1; thensed -nl "$@"elselocal pad="$(printf "\n%512s" "")"sed -ne "s/$/\\${pad}/" "$@"fi}print_progress() {local bytes="1ドル"local length="2ドル"[ "$length" -gt 0 ] || return 0local width=50local percent=$(( bytes * 100 / length ))[ "$percent" -gt 100 ] && percent=100local on=$(( percent * width / 100 ))local off=$(( width - on ))local filled=$(printf "%*s" "$on" "")filled=${filled// /■しかく}local empty=$(printf "%*s" "$off" "")empty=${empty// /・}printf "\r${ORANGE}%s%s %3d%%${NC}" "$filled" "$empty" "$percent" >&4}download_with_progress() {local url="1ドル"local output="2ドル"if [ -t 2 ]; thenexec 4>&2elseexec 4>/dev/nullfilocal tmp_dir=${TMPDIR:-/tmp}local basename="${tmp_dir}/opencode_install_$$"local tracefile="${basename}.trace"rm -f "$tracefile"mkfifo "$tracefile"# Hide cursorprintf "0円33[?25l" >&4trap "trap - RETURN; rm -f \"$tracefile\"; printf '0円33[?25h' >&4; exec 4>&-" RETURN(curl --trace-ascii "$tracefile" -s -L -o "$output" "$url") &local curl_pid=$!unbuffered_sed \-e 'y/ACDEGHLNORTV/acdeghlnortv/' \-e '/^0000: content-length:/p' \-e '/^<= recv data/p' \"$tracefile" | \{local length=0local bytes=0while IFS=" " read -r -a line; do[ "${#line[@]}" -lt 2 ] && continuelocal tag="${line[0]}${line[1]}"if [ "$tag" = "0000: content-length:" ]; thenlength="${line[2]}"length=$(echo "$length" | tr -d '\r')bytes=0elif [ "$tag" = "<= recv" ]; thenlocal size="${line[3]}"bytes=$(( bytes + size ))if [ "$length" -gt 0 ]; thenprint_progress "$bytes" "$length"fifidone}wait $curl_pidlocal ret=$?echo "" >&4return $ret}download_and_install() {print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}version: ${NC}$specific_version"local tmp_dir="${TMPDIR:-/tmp}/opencode_install_$$"mkdir -p "$tmp_dir"if [[ "$os" == "windows" ]] || ! [ -t 2 ] || ! download_with_progress "$url" "$tmp_dir/$filename"; then# Fallback to standard curl on Windows, non-TTY environments, or if custom progress failscurl -# -L -o "$tmp_dir/$filename" "$url"fiif [ "$os" = "linux" ]; thentar -xzf "$tmp_dir/$filename" -C "$tmp_dir"elseunzip -q "$tmp_dir/$filename" -d "$tmp_dir"fimv "$tmp_dir/opencode" "$INSTALL_DIR"chmod 755 "${INSTALL_DIR}/opencode"rm -rf "$tmp_dir"}install_from_binary() {print_message info "\n${MUTED}Installing ${NC}opencode ${MUTED}from: ${NC}$binary_path"cp "$binary_path" "${INSTALL_DIR}/opencode"chmod 755 "${INSTALL_DIR}/opencode"}if [ -n "$binary_path" ]; theninstall_from_binaryelsecheck_versiondownload_and_installfiadd_to_path() {local config_file=1ドルlocal command=2ドルif grep -Fxq "$command" "$config_file"; thenprint_message info "Command already exists in $config_file, skipping write."elif [[ -w $config_file ]]; thenecho -e "\n# opencode" >> "$config_file"echo "$command" >> "$config_file"print_message info "${MUTED}Successfully added ${NC}opencode ${MUTED}to \$PATH in ${NC}$config_file"elseprint_message warning "Manually add the directory to $config_file (or similar):"print_message info " $command"fi}XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}current_shell=$(basename "$SHELL")case $current_shell infish)config_files="$HOME/.config/fish/config.fish";;zsh)config_files="${ZDOTDIR:-$HOME}/.zshrc ${ZDOTDIR:-$HOME}/.zshenv $XDG_CONFIG_HOME/zsh/.zshrc $XDG_CONFIG_HOME/zsh/.zshenv";;bash)config_files="$HOME/.bashrc $HOME/.bash_profile $HOME/.profile $XDG_CONFIG_HOME/bash/.bashrc $XDG_CONFIG_HOME/bash/.bash_profile";;ash)config_files="$HOME/.ashrc $HOME/.profile /etc/profile";;sh)config_files="$HOME/.ashrc $HOME/.profile /etc/profile";;*)# Default case if none of the above matchesconfig_files="$HOME/.bashrc $HOME/.bash_profile $XDG_CONFIG_HOME/bash/.bashrc $XDG_CONFIG_HOME/bash/.bash_profile";;esacif [[ "$no_modify_path" != "true" ]]; thenconfig_file=""for file in $config_files; doif [[ -f $file ]]; thenconfig_file=$filebreakfidoneif [[ -z $config_file ]]; thenprint_message warning "No config file found for $current_shell. You may need to manually add to PATH:"print_message info " export PATH=$INSTALL_DIR:\$PATH"elif [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; thencase $current_shell infish)add_to_path "$config_file" "fish_add_path $INSTALL_DIR";;zsh)add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH";;bash)add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH";;ash)add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH";;sh)add_to_path "$config_file" "export PATH=$INSTALL_DIR:\$PATH";;*)export PATH=$INSTALL_DIR:$PATHprint_message warning "Manually add the directory to $config_file (or similar):"print_message info " export PATH=$INSTALL_DIR:\$PATH";;esacfifiif [ -n "${GITHUB_ACTIONS-}" ] && [ "${GITHUB_ACTIONS}" == "true" ]; thenecho "$INSTALL_DIR" >> $GITHUB_PATHprint_message info "Added $INSTALL_DIR to \$GITHUB_PATH"fiecho -e ""echo -e "${MUTED}${NC} ▄ "echo -e "${MUTED}█▀▀█ █▀▀█ █▀▀█ █▀▀▄ ${NC}█▀▀▀ █▀▀█ █▀▀█ █▀▀█"echo -e "${MUTED}█░░█ █░░█ █▀▀▀ █░░█ ${NC}█░░░ █░░█ █░░█ █▀▀▀"echo -e "${MUTED}▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀ ${NC}▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀"echo -e ""echo -e ""echo -e "${MUTED}OpenCode includes free models, to start:${NC}"echo -e ""echo -e "cd <project> ${MUTED}# Open directory${NC}"echo -e "opencode ${MUTED}# Run command${NC}"echo -e ""echo -e "${MUTED}For more information visit ${NC}https://opencode.ai/docs"echo -e ""echo -e ""
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。