feat(install): all-in-one bootstrap — install OpenCode then the fork
- install.sh now ensures the OpenCode runtime is present: detects it on PATH or at $HOME/.opencode/bin, and otherwise runs the official installer (opencode.ai/v2/install) - new flags: --with-opencode, --no-opencode, --opencode-version V, --opencode-no-path - --dry-run never installs the runtime; OPENCODE_INSTALLER_URL can be overridden (mirrors/tests) - README documents the all-in-one behaviour and the new runtime flags
This commit is contained in:
parent
c8347acfe4
commit
2e1f8ca525
2 changed files with 126 additions and 5 deletions
12
README.md
12
README.md
|
|
@ -136,6 +136,8 @@ env.example template for the optional .env (Telegram/Gemini integrations)
|
||||||
|
|
||||||
This repository is **private**, so the installer needs access to it. The simplest path is to clone it once and run the installer from the clone — your existing git credentials are used, no token to paste.
|
This repository is **private**, so the installer needs access to it. The simplest path is to clone it once and run the installer from the clone — your existing git credentials are used, no token to paste.
|
||||||
|
|
||||||
|
The installer is **all-in-one**: if OpenCode isn't already installed, it bootstraps the runtime first (from the official installer at [`opencode.ai/v2/install`](https://opencode.ai/v2/install)), then installs the fork.
|
||||||
|
|
||||||
### Recommended — clone, then install
|
### Recommended — clone, then install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -165,6 +167,10 @@ The installer offers **Local** (`.opencode/` in the current project), **Global**
|
||||||
| `--install-dir PATH` | install into an exact path |
|
| `--install-dir PATH` | install into an exact path |
|
||||||
| `--source DIR` | install from a local clone instead of downloading |
|
| `--source DIR` | install from a local clone instead of downloading |
|
||||||
| `--branch REF` | branch/tag to install from (default `main`) |
|
| `--branch REF` | branch/tag to install from (default `main`) |
|
||||||
|
| `--with-opencode` | install/update OpenCode even if it is already present |
|
||||||
|
| `--no-opencode` | skip the OpenCode runtime install |
|
||||||
|
| `--opencode-version V` | install a specific OpenCode version |
|
||||||
|
| `--opencode-no-path` | don't let the OpenCode installer edit your shell PATH |
|
||||||
| `--yes` / `-y` | non-interactive; skip existing files |
|
| `--yes` / `-y` | non-interactive; skip existing files |
|
||||||
| `--force` | non-interactive; overwrite existing files |
|
| `--force` | non-interactive; overwrite existing files |
|
||||||
| `--dry-run` | show what would happen, change nothing |
|
| `--dry-run` | show what would happen, change nothing |
|
||||||
|
|
@ -180,6 +186,12 @@ cp -R /tmp/oac/agent /tmp/oac/command /tmp/oac/context \
|
||||||
/tmp/oac/package.json .opencode/
|
/tmp/oac/package.json .opencode/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This copies the **fork only** — install the OpenCode **runtime** first if it's missing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://opencode.ai/v2/install | bash
|
||||||
|
```
|
||||||
|
|
||||||
Then start OpenCode and pick your agent:
|
Then start OpenCode and pick your agent:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
119
install.sh
119
install.sh
|
|
@ -2,8 +2,9 @@
|
||||||
#
|
#
|
||||||
# OpenAgents Control — Architect Fork · installer
|
# OpenAgents Control — Architect Fork · installer
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Installs the OAC Architect Fork — the agents, subagents, commands, context,
|
# All-in-one bootstrap: installs OpenCode (the runtime) when it is missing, then
|
||||||
# skills and tools — into a project's .opencode/ directory or the global
|
# the OAC Architect Fork — the agents, subagents, commands, context, skills and
|
||||||
|
# tools — into a project's .opencode/ directory or the global
|
||||||
# ~/.config/opencode/ directory.
|
# ~/.config/opencode/ directory.
|
||||||
#
|
#
|
||||||
# Adapted from Darren Hinde's OpenAgents Control installer (MIT).
|
# Adapted from Darren Hinde's OpenAgents Control installer (MIT).
|
||||||
|
|
@ -22,6 +23,7 @@
|
||||||
# ./install.sh --source DIR # install from a local clone
|
# ./install.sh --source DIR # install from a local clone
|
||||||
# ./install.sh --global --yes # non-interactive, skip existing files
|
# ./install.sh --global --yes # non-interactive, skip existing files
|
||||||
# ./install.sh --global --force # non-interactive, overwrite existing
|
# ./install.sh --global --force # non-interactive, overwrite existing
|
||||||
|
# ./install.sh --no-opencode # install the fork only (skip OpenCode)
|
||||||
# ./install.sh --dry-run # show the plan, change nothing
|
# ./install.sh --dry-run # show the plan, change nothing
|
||||||
#
|
#
|
||||||
# Environment:
|
# Environment:
|
||||||
|
|
@ -46,6 +48,10 @@ TOKEN="${OAC_TOKEN:-}"
|
||||||
PAYLOAD_DIRS="agent command context skills tool"
|
PAYLOAD_DIRS="agent command context skills tool"
|
||||||
PAYLOAD_FILES="env.example package.json"
|
PAYLOAD_FILES="env.example package.json"
|
||||||
|
|
||||||
|
# OpenCode runtime — the official installer places the binary in $HOME/.opencode/bin
|
||||||
|
OPENCODE_INSTALLER_URL="${OPENCODE_INSTALLER_URL:-https://opencode.ai/v2/install}"
|
||||||
|
OPENCODE_BIN_DIR="${HOME}/.opencode/bin"
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Colours (only when writing to a terminal)
|
# Colours (only when writing to a terminal)
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -81,7 +87,8 @@ usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
OpenAgents Control — Architect Fork · installer
|
OpenAgents Control — Architect Fork · installer
|
||||||
|
|
||||||
Installs the OAC Architect Fork into a project's .opencode/ or the global
|
All-in-one bootstrap: installs OpenCode (the runtime) if it is missing, then
|
||||||
|
the OAC Architect Fork into a project's .opencode/ or the global
|
||||||
~/.config/opencode/ directory.
|
~/.config/opencode/ directory.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
@ -98,6 +105,12 @@ Source:
|
||||||
--branch REF Branch/tag to fetch (default: main)
|
--branch REF Branch/tag to fetch (default: main)
|
||||||
--token TOKEN Forgejo token with repo:read (private fetch)
|
--token TOKEN Forgejo token with repo:read (private fetch)
|
||||||
|
|
||||||
|
Runtime:
|
||||||
|
--with-opencode Install/update OpenCode even if it is already present
|
||||||
|
--no-opencode Skip the OpenCode install
|
||||||
|
--opencode-version V Install a specific OpenCode version
|
||||||
|
--opencode-no-path Don't let the OpenCode installer edit your shell PATH
|
||||||
|
|
||||||
Behaviour:
|
Behaviour:
|
||||||
-y, --yes Non-interactive; skip files that already exist
|
-y, --yes Non-interactive; skip files that already exist
|
||||||
--force Non-interactive; overwrite existing files
|
--force Non-interactive; overwrite existing files
|
||||||
|
|
@ -125,6 +138,9 @@ ASSUME_YES=0
|
||||||
FORCE=0
|
FORCE=0
|
||||||
DRY_RUN=0
|
DRY_RUN=0
|
||||||
SOURCE=""
|
SOURCE=""
|
||||||
|
OPENCODE_MODE="auto" # auto | yes | no
|
||||||
|
OPENCODE_VERSION=""
|
||||||
|
OPENCODE_NO_PATH=0
|
||||||
|
|
||||||
while [ $# -gt 0 ]; do
|
while [ $# -gt 0 ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
@ -141,6 +157,11 @@ while [ $# -gt 0 ]; do
|
||||||
-y|--yes) ASSUME_YES=1 ;;
|
-y|--yes) ASSUME_YES=1 ;;
|
||||||
--force) ASSUME_YES=1; FORCE=1 ;;
|
--force) ASSUME_YES=1; FORCE=1 ;;
|
||||||
--dry-run) DRY_RUN=1 ;;
|
--dry-run) DRY_RUN=1 ;;
|
||||||
|
--with-opencode|--opencode) OPENCODE_MODE="yes" ;;
|
||||||
|
--no-opencode) OPENCODE_MODE="no" ;;
|
||||||
|
--opencode-version) [ $# -ge 2 ] || die "--opencode-version needs a version"; OPENCODE_VERSION="$2"; shift ;;
|
||||||
|
--opencode-version=*) OPENCODE_VERSION="${1#*=}" ;;
|
||||||
|
--opencode-no-path) OPENCODE_NO_PATH=1 ;;
|
||||||
-h|--help) usage; exit 0 ;;
|
-h|--help) usage; exit 0 ;;
|
||||||
*) error "Unknown option: $1"; echo; usage; exit 1 ;;
|
*) error "Unknown option: $1"; echo; usage; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -158,6 +179,88 @@ if [ -n "$TOKEN" ]; then
|
||||||
command -v curl >/dev/null 2>&1 || die "curl is required when using --token"
|
command -v curl >/dev/null 2>&1 || die "curl is required when using --token"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# OpenCode runtime (all-in-one bootstrap)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
have_opencode() {
|
||||||
|
command -v opencode >/dev/null 2>&1 && return 0
|
||||||
|
[ -x "${OPENCODE_BIN_DIR}/opencode" ] && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
opencode_path() {
|
||||||
|
if command -v opencode >/dev/null 2>&1; then
|
||||||
|
command -v opencode
|
||||||
|
else
|
||||||
|
printf '%s' "${OPENCODE_BIN_DIR}/opencode"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_opencode() {
|
||||||
|
if [ "$DRY_RUN" = 1 ]; then
|
||||||
|
if have_opencode; then
|
||||||
|
info "[dry-run] OpenCode already present — $(opencode_path)"
|
||||||
|
elif [ "$OPENCODE_MODE" = "no" ]; then
|
||||||
|
info "[dry-run] would skip OpenCode (--no-opencode)"
|
||||||
|
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)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$OPENCODE_MODE" = "no" ]; then
|
||||||
|
info "Skipping the OpenCode install (--no-opencode)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$OPENCODE_MODE" = "auto" ] && ! have_opencode && [ -t 0 ] && [ -t 1 ]; then
|
||||||
|
printf "${BOLD}OpenCode is not installed. Install it now?${NC} [Y/n]: "
|
||||||
|
ans=""
|
||||||
|
read -r ans || true
|
||||||
|
case "$ans" in
|
||||||
|
[Nn]*) info "Skipping OpenCode."; return 0 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
command -v curl >/dev/null 2>&1 || die "curl is required to install OpenCode"
|
||||||
|
|
||||||
|
step "Installing OpenCode…"
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp 2>/dev/null || mktemp -t oac)"
|
||||||
|
if ! curl -fsSL "$OPENCODE_INSTALLER_URL" -o "$tmp"; then
|
||||||
|
rm -f "$tmp"
|
||||||
|
die "Could not download the OpenCode installer (${OPENCODE_INSTALLER_URL})"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local ok=0
|
||||||
|
if [ -n "$OPENCODE_VERSION" ] && [ "$OPENCODE_NO_PATH" = 1 ]; then
|
||||||
|
bash "$tmp" --no-modify-path --version "$OPENCODE_VERSION" && ok=1
|
||||||
|
elif [ -n "$OPENCODE_VERSION" ]; then
|
||||||
|
bash "$tmp" --version "$OPENCODE_VERSION" && ok=1
|
||||||
|
elif [ "$OPENCODE_NO_PATH" = 1 ]; then
|
||||||
|
bash "$tmp" --no-modify-path && ok=1
|
||||||
|
else
|
||||||
|
bash "$tmp" && ok=1
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
[ "$ok" = 1 ] || die "OpenCode installation failed"
|
||||||
|
|
||||||
|
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."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Resolve the source payload
|
# Resolve the source payload
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -377,8 +480,13 @@ show_post_install() {
|
||||||
if [ -f "$INSTALL_DIR/env.example" ]; then
|
if [ -f "$INSTALL_DIR/env.example" ]; then
|
||||||
echo "2. (Optional) configure integrations: ${CYAN}cp ${INSTALL_DIR}/env.example .env${NC}"
|
echo "2. (Optional) configure integrations: ${CYAN}cp ${INSTALL_DIR}/env.example .env${NC}"
|
||||||
fi
|
fi
|
||||||
echo "3. Start OpenCode and pick an agent:"
|
if have_opencode; then
|
||||||
echo -e " ${CYAN}opencode${NC} → choose ${BOLD}OpenArchitect${NC} to spec/verify, ${BOLD}OpenAgent${NC} to build"
|
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"
|
||||||
|
else
|
||||||
|
echo "3. Install OpenCode, then pick an agent:"
|
||||||
|
echo -e " ${CYAN}curl -fsSL ${OPENCODE_INSTALLER_URL} | bash${NC}"
|
||||||
|
fi
|
||||||
echo
|
echo
|
||||||
info "Docs: ${REPO_URL}"
|
info "Docs: ${REPO_URL}"
|
||||||
}
|
}
|
||||||
|
|
@ -388,6 +496,7 @@ show_post_install() {
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
main() {
|
main() {
|
||||||
print_header
|
print_header
|
||||||
|
ensure_opencode
|
||||||
resolve_source
|
resolve_source
|
||||||
resolve_install_dir
|
resolve_install_dir
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue