@@ -16,16 +16,19 @@ Usage: install.sh [options]
1616Options:
1717 -h, --help Display this help message
1818 -v, --version <version> Install a specific version (e.g., 1.0.180)
19+ -b, --binary <path> Install from a local binary instead of downloading
1920 --no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
2021
2122Examples:
2223 curl -fsSL https://opencode.ai/install | bash
2324 curl -fsSL https://opencode.ai/install | bash -s -- --version 1.0.180
25+ ./install --binary /path/to/opencode
2426EOF
2527}
2628
2729requested_version=${VERSION:- }
2830no_modify_path=false
31+ binary_path=" "
2932
3033while [[ $# -gt 0 ]]; do
3134 case " $1 " in
@@ -42,6 +45,15 @@ while [[ $# -gt 0 ]]; do
4245 exit 1
4346 fi
4447 ;;
48+ -b|--binary)
49+ if [[ -n " ${2:- } " ]]; then
50+ binary_path=" $2 "
51+ shift 2
52+ else
53+ echo -e " ${RED} Error: --binary requires a path argument${NC} "
54+ exit 1
55+ fi
56+ ;;
4557 --no-modify-path)
4658 no_modify_path=true
4759 shift
@@ -53,119 +65,128 @@ while [[ $# -gt 0 ]]; do
5365 esac
5466done
5567
56- raw_os=$( uname -s)
57- os=$( echo " $raw_os " | tr ' [:upper:]' ' [:lower:]' )
58- case " $raw_os " in
59- Darwin* ) os=" darwin" ;;
60- Linux* ) os=" linux" ;;
61- MINGW* |MSYS* |CYGWIN* ) os=" windows" ;;
62- esac
63-
64- arch=$( uname -m)
65- if [[ " $arch " == " aarch64" ]]; then
66- arch=" arm64"
67- fi
68- if [[ " $arch " == " x86_64" ]]; then
69- arch=" x64"
70- fi
68+ INSTALL_DIR=$HOME /.opencode/bin
69+ mkdir -p " $INSTALL_DIR "
7170
72- if [ " $os " = " darwin" ] && [ " $arch " = " x64" ]; then
73- rosetta_flag=$( sysctl -n sysctl.proc_translated 2> /dev/null || echo 0)
74- if [ " $rosetta_flag " = " 1" ]; then
75- arch=" arm64"
76- fi
77- fi
71+ # If --binary is provided, skip all download/detection logic
72+ if [ -n " $binary_path " ]; then
73+ if [ ! -f " $binary_path " ]; then
74+ echo -e " ${RED} Error: Binary not found at ${binary_path}${NC} "
75+ exit 1
76+ fi
77+ specific_version=" local"
78+ else
79+ raw_os=$( uname -s)
80+ os=$( echo " $raw_os " | tr ' [:upper:]' ' [:lower:]' )
81+ case " $raw_os " in
82+ Darwin* ) os=" darwin" ;;
83+ Linux* ) os=" linux" ;;
84+ MINGW* |MSYS* |CYGWIN* ) os=" windows" ;;
85+ esac
7886
79- combo=" $os -$arch "
80- case " $combo " in
81- linux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64)
82- ;;
83- * )
84- echo -e " ${RED} Unsupported OS/Arch: $os /$arch ${NC} "
85- exit 1
86- ;;
87- esac
87+ arch=$( uname -m)
88+ if [[ " $arch " == " aarch64" ]]; then
89+ arch=" arm64"
90+ fi
91+ if [[ " $arch " == " x86_64" ]]; then
92+ arch=" x64"
93+ fi
8894
89- archive_ext=" .zip"
90- if [ " $os " = " linux" ]; then
91- archive_ext=" .tar.gz"
92- fi
95+ if [ " $os " = " darwin" ] && [ " $arch " = " x64" ]; then
96+ rosetta_flag=$( sysctl -n sysctl.proc_translated 2> /dev/null || echo 0)
97+ if [ " $rosetta_flag " = " 1" ]; then
98+ arch=" arm64"
99+ fi
100+ fi
93101
94- is_musl=false
95- if [ " $os " = " linux" ]; then
96- if [ -f /etc/alpine-release ]; then
97- is_musl=true
98- fi
102+ combo=" $os -$arch "
103+ case " $combo " in
104+ linux-x64|linux-arm64|darwin-x64|darwin-arm64|windows-x64)
105+ ;;
106+ * )
107+ echo -e " ${RED} Unsupported OS/Arch: $os /$arch ${NC} "
108+ exit 1
109+ ;;
110+ esac
99111
100- if command -v ldd > /dev/null 2>&1 ; then
101- if ldd --version 2>&1 | grep -qi musl ; then
102- is_musl=true
112+ archive_ext= " .zip "
113+ if [ " $os " = " linux " ] ; then
114+ archive_ext= " .tar.gz "
103115 fi
104- fi
105- fi
106116
107- needs_baseline=false
108- if [ " $arch " = " x64" ]; then
109- if [ " $os " = " linux" ]; then
110- if ! grep -qi avx2 /proc/cpuinfo 2> /dev/null; then
111- needs_baseline=true
112- fi
113- fi
117+ is_musl=false
118+ if [ " $os " = " linux" ]; then
119+ if [ -f /etc/alpine-release ]; then
120+ is_musl=true
121+ fi
114122
115- if [ " $os " = " darwin" ]; then
116- avx2=$( sysctl -n hw.optional.avx2_0 2> /dev/null || echo 0)
117- if [ " $avx2 " != " 1" ]; then
118- needs_baseline=true
123+ if command -v ldd > /dev/null 2>&1 ; then
124+ if ldd --version 2>&1 | grep -qi musl; then
125+ is_musl=true
126+ fi
127+ fi
119128 fi
120- fi
121- fi
122129
123- target=" $os -$arch "
124- if [ " $needs_baseline " = " true" ]; then
125- target=" $target -baseline"
126- fi
127- if [ " $is_musl " = " true" ]; then
128- target=" $target -musl"
129- fi
130-
131- filename=" $APP -$target$archive_ext "
130+ needs_baseline=false
131+ if [ " $arch " = " x64" ]; then
132+ if [ " $os " = " linux" ]; then
133+ if ! grep -qi avx2 /proc/cpuinfo 2> /dev/null; then
134+ needs_baseline=true
135+ fi
136+ fi
132137
138+ if [ " $os " = " darwin" ]; then
139+ avx2=$( sysctl -n hw.optional.avx2_0 2> /dev/null || echo 0)
140+ if [ " $avx2 " != " 1" ]; then
141+ needs_baseline=true
142+ fi
143+ fi
144+ fi
133145
134- if [ " $os " = " linux" ]; then
135- if ! command -v tar > /dev/null 2>&1 ; then
136- echo -e " ${RED} Error: 'tar' is required but not installed.${NC} "
137- exit 1
146+ target=" $os -$arch "
147+ if [ " $needs_baseline " = " true" ]; then
148+ target=" $target -baseline"
138149 fi
139- else
140- if ! command -v unzip > /dev/null 2>&1 ; then
141- echo -e " ${RED} Error: 'unzip' is required but not installed.${NC} "
142- exit 1
150+ if [ " $is_musl " = " true" ]; then
151+ target=" $target -musl"
143152 fi
144- fi
145153
146- INSTALL_DIR=$HOME /.opencode/bin
147- mkdir -p " $INSTALL_DIR "
154+ filename=" $APP -$target$archive_ext "
148155
149- if [ -z " $requested_version " ]; then
150- url=" https://github.com/anomalyco/opencode/releases/latest/download/$filename "
151- specific_version=$( curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest | sed -n ' s/.*"tag_name": *"v\([^"]*\)".*/\1/p' )
152156
153- if [[ $? -ne 0 || -z " $specific_version " ]]; then
154- echo -e " ${RED} Failed to fetch version information${NC} "
155- exit 1
157+ if [ " $os " = " linux" ]; then
158+ if ! command -v tar > /dev/null 2>&1 ; then
159+ echo -e " ${RED} Error: 'tar' is required but not installed.${NC} "
160+ exit 1
161+ fi
162+ else
163+ if ! command -v unzip > /dev/null 2>&1 ; then
164+ echo -e " ${RED} Error: 'unzip' is required but not installed.${NC} "
165+ exit 1
166+ fi
156167 fi
157- else
158- # Strip leading 'v' if present
159- requested_version=" ${requested_version# v} "
160- url=" https://github.com/anomalyco/opencode/releases/download/v${requested_version} /$filename "
161- specific_version=$requested_version
162-
163- # Verify the release exists before downloading
164- http_status=$( curl -sI -o /dev/null -w " %{http_code}" " https://github.com/anomalyco/opencode/releases/tag/v${requested_version} " )
165- if [ " $http_status " = " 404" ]; then
166- echo -e " ${RED} Error: Release v${requested_version} not found${NC} "
167- echo -e " ${MUTED} Available releases: https://github.com/anomalyco/opencode/releases${NC} "
168- exit 1
168+
169+ if [ -z " $requested_version " ]; then
170+ url=" https://github.com/anomalyco/opencode/releases/latest/download/$filename "
171+ specific_version=$( curl -s https://api.github.com/repos/anomalyco/opencode/releases/latest | sed -n ' s/.*"tag_name": *"v\([^"]*\)".*/\1/p' )
172+
173+ if [[ $? -ne 0 || -z " $specific_version " ]]; then
174+ echo -e " ${RED} Failed to fetch version information${NC} "
175+ exit 1
176+ fi
177+ else
178+ # Strip leading 'v' if present
179+ requested_version=" ${requested_version# v} "
180+ url=" https://github.com/anomalyco/opencode/releases/download/v${requested_version} /$filename "
181+ specific_version=$requested_version
182+
183+ # Verify the release exists before downloading
184+ http_status=$( curl -sI -o /dev/null -w " %{http_code}" " https://github.com/anomalyco/opencode/releases/tag/v${requested_version} " )
185+ if [ " $http_status " = " 404" ]; then
186+ echo -e " ${RED} Error: Release v${requested_version} not found${NC} "
187+ echo -e " ${MUTED} Available releases: https://github.com/anomalyco/opencode/releases${NC} "
188+ exit 1
189+ fi
169190 fi
170191fi
171192
@@ -267,11 +288,11 @@ download_with_progress() {
267288 {
268289 local length=0
269290 local bytes=0
270-
291+
271292 while IFS=" " read -r -a line; do
272293 [ " ${# line[@]} " -lt 2 ] && continue
273294 local tag=" ${line[0]} ${line[1]} "
274-
295+
275296 if [ " $tag " = " 0000: content-length:" ]; then
276297 length=" ${line[2]} "
277298 length=$( echo " $length " | tr -d ' \r' )
@@ -296,7 +317,7 @@ download_and_install() {
296317 print_message info " \n${MUTED} Installing ${NC} opencode ${MUTED} version: ${NC} $specific_version "
297318 local tmp_dir=" ${TMPDIR:-/ tmp} /opencode_install_$$ "
298319 mkdir -p " $tmp_dir "
299-
320+
300321 if [[ " $os " == " windows" ]] || ! [ -t 2 ] || ! download_with_progress " $url " " $tmp_dir /$filename " ; then
301322 # Fallback to standard curl on Windows, non-TTY environments, or if custom progress fails
302323 curl -# -L -o " $tmp_dir /$filename " " $url "
@@ -307,14 +328,24 @@ download_and_install() {
307328 else
308329 unzip -q " $tmp_dir /$filename " -d " $tmp_dir "
309330 fi
310-
331+
311332 mv " $tmp_dir /opencode" " $INSTALL_DIR "
312333 chmod 755 " ${INSTALL_DIR} /opencode"
313334 rm -rf " $tmp_dir "
314335}
315336
316- check_version
317- download_and_install
337+ install_from_binary () {
338+ print_message info " \n${MUTED} Installing ${NC} opencode ${MUTED} from: ${NC} $binary_path "
339+ cp " $binary_path " " ${INSTALL_DIR} /opencode"
340+ chmod 755 " ${INSTALL_DIR} /opencode"
341+ }
342+
343+ if [ -n " $binary_path " ]; then
344+ install_from_binary
345+ else
346+ check_version
347+ download_and_install
348+ fi
318349
319350
320351add_to_path () {
@@ -416,4 +447,3 @@ echo -e ""
416447echo -e " ${MUTED} For more information visit ${NC} https://opencode.ai/docs"
417448echo -e " "
418449echo -e " "
419-
0 commit comments