From b2939d525a2f03c390a310a99023bd41eef6edb2 Mon Sep 17 00:00:00 2001 From: cclohmar Date: Tue, 13 Oct 2026 07:32:43 +0000 Subject: [PATCH] fix(install): detect and offer to activate OpenCode on PATH - ensure_opencode no longer reports 'already installed' when the binary exists but isn't reachable; it now reports the PATH gap - activate_opencode: explains the rc line / 'source ~/.bashrc', and interactively offers to symlink opencode into /usr/local/bin so it works immediately in every shell - post-install hint reflects whether opencode is actually on PATH - README: PATH & activation section --- README.md | 8 ++++++ install.sh | 72 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2b6afe8..f2df2e5 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,14 @@ The installer offers **Local** (`.opencode/` in the current project), **Global** | `--dry-run` | show what would happen, change nothing | | `--help` | usage | +### PATH & activation + +The official OpenCode installer appends `export PATH="$HOME/.opencode/bin:$PATH"` to your shell rc (`~/.bashrc` for bash) — but it does **not** activate it in the running shell, and an installer cannot change its parent shell. So: + +- **New terminal** → `opencode` is on your PATH. +- **Same terminal** → `source ~/.bashrc` (or your shell's rc file). +- If the binary is present but not yet reachable, the installer says so at the end and, interactively, offers to **symlink it into `/usr/local/bin`** so it works immediately in every shell. + ### Manual install ```bash diff --git a/install.sh b/install.sh index 6cf1d2a..a796435 100755 --- a/install.sh +++ b/install.sh @@ -204,25 +204,70 @@ opencode_path() { fi } +opencode_on_path() { command -v opencode >/dev/null 2>&1; } + +# The official installer writes the PATH line to the shell rc but never activates +# it. Report that, and offer to make `opencode` work immediately via a symlink. +activate_opencode() { + opencode_on_path && return 0 + have_opencode || return 0 + + warn "OpenCode is installed at ${OPENCODE_BIN_DIR} but is not on your PATH yet." + if [ "$OPENCODE_NO_PATH" = 1 ]; then + info "PATH was left untouched (--opencode-no-path). Add it yourself: export PATH=\"${OPENCODE_BIN_DIR}:\$PATH\"" + return 0 + fi + + local rc="" + case "$(basename "${SHELL:-bash}")" in + bash) [ -f "$HOME/.bashrc" ] && rc="$HOME/.bashrc" ;; + zsh) [ -f "$HOME/.zshrc" ] && rc="$HOME/.zshrc" ;; + *) [ -f "$HOME/.profile" ] && rc="$HOME/.profile" ;; + esac + if [ -n "$rc" ] && grep -q "${OPENCODE_BIN_DIR}" "$rc" 2>/dev/null; then + info "A PATH line is already in ${rc} — run source ${rc} or open a new terminal." + else + info "Add it to your shell profile: export PATH=\"${OPENCODE_BIN_DIR}:\$PATH\"" + fi + + if [ -t 0 ] && [ -t 1 ]; then + printf "${BOLD}Make 'opencode' available now (symlink into /usr/local/bin)?${NC} [y/N]: " + ans=""; read -r ans || true + case "$ans" in + [Yy]*) + local sudo="" + [ "$(id -u)" != "0" ] && sudo="sudo" + if $sudo ln -sf "${OPENCODE_BIN_DIR}/opencode" /usr/local/bin/opencode 2>/dev/null; then + success "Linked /usr/local/bin/opencode — 'opencode' now works in this and every shell." + else + warn "Could not create the symlink — use: export PATH=\"${OPENCODE_BIN_DIR}:\$PATH\"" + fi + ;; + esac + fi + return 0 +} + ensure_opencode() { if [ "$DRY_RUN" = 1 ]; then - if have_opencode; then - info "[dry-run] OpenCode already present — $(opencode_path)" - elif [ "$OPENCODE_MODE" = "no" ]; then + if [ "$OPENCODE_MODE" = "no" ]; then info "[dry-run] would skip OpenCode (--no-opencode)" + elif have_opencode; then + info "[dry-run] OpenCode already present — $(opencode_path)" else info "[dry-run] would install OpenCode from ${OPENCODE_INSTALLER_URL}" fi return 0 fi - if have_opencode && [ "$OPENCODE_MODE" != "yes" ]; then - success "OpenCode is already installed — $(opencode_path)" + if [ "$OPENCODE_MODE" = "no" ]; then + info "Skipping the OpenCode install (--no-opencode)" return 0 fi - if [ "$OPENCODE_MODE" = "no" ]; then - info "Skipping the OpenCode install (--no-opencode)" + if have_opencode && [ "$OPENCODE_MODE" != "yes" ]; then + success "OpenCode is already installed — $(opencode_path)" + activate_opencode return 0 fi @@ -260,13 +305,11 @@ ensure_opencode() { if have_opencode; then success "OpenCode installed — $(opencode_path)" - case ":$PATH:" in - *":${OPENCODE_BIN_DIR}:"*) : ;; - *) warn "Add OpenCode to your PATH: export PATH=\"${OPENCODE_BIN_DIR}:\$PATH\"" ;; - esac else - warn "The OpenCode installer finished, but 'opencode' is not on PATH yet. Re-open your shell and try again." + warn "The OpenCode installer finished, but the binary was not found at ${OPENCODE_BIN_DIR}/opencode." fi + activate_opencode + return 0 } # --------------------------------------------------------------------------- @@ -600,9 +643,12 @@ show_post_install() { if [ -f "$INSTALL_DIR/env.example" ]; then echo "2. (Optional) configure integrations: ${CYAN}cp ${INSTALL_DIR}/env.example .env${NC}" fi - if have_opencode; then + if opencode_on_path; then echo "3. Start OpenCode and pick an agent:" echo -e " ${CYAN}opencode${NC} → choose ${BOLD}OpenArchitect${NC} to spec/verify, ${BOLD}OpenAgent${NC} to build" + elif have_opencode; then + echo "3. OpenCode is installed but not on PATH yet — get it available:" + echo -e " ${CYAN}export PATH=\"${OPENCODE_BIN_DIR}:\$PATH\"${NC} (or open a new terminal)" else echo "3. Install OpenCode, then pick an agent:" echo -e " ${CYAN}curl -fsSL ${OPENCODE_INSTALLER_URL} | bash${NC}"