diff --git a/opencode/README.md b/opencode/README.md new file mode 100644 index 000000000..d63d7b602 --- /dev/null +++ b/opencode/README.md @@ -0,0 +1,120 @@ +--- +title: opencode +homepage: https://github.com/anomalyco/opencode +tagline: | + opencode: A terminal-based AI coding agent with multi-provider LLM support. +--- + +To update or switch versions, run `webi opencode@stable` (or `@v1.2`, `@beta`, +etc). + +### Files + +These are the files / directories that are created and/or modified with this +install: + +```text +~/.config/envman/PATH.env +~/.local/bin/opencode +~/.local/opt/opencode-VERSION/bin/opencode +~/.config/opencode/opencode.json +``` + +## Cheat Sheet + +> `opencode` is an AI coding agent that runs in the terminal. It connects to LLM +> providers (Anthropic, OpenAI, Google, or local models via Ollama) and gives +> you an interactive TUI with full tool use — file editing, shell commands, and +> codebase navigation. + +### How to Get Started + +Set an API key and launch in your project directory: + +```sh +export ANTHROPIC_API_KEY="sk-ant-..." +cd ~/your-project +opencode +``` + +opencode starts a TUI where you can chat, edit files, run commands, and navigate +your codebase. + +### How to Configure Providers + +Add providers to `~/.config/opencode/opencode.json`: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": {}, + "openai": {} + }, + "model": { + "big": "anthropic/claude-sonnet-4-5-20250514", + "small": "anthropic/claude-haiku-4-5-20250514" + } +} +``` + +Anthropic reads `ANTHROPIC_API_KEY`, OpenAI reads `OPENAI_API_KEY`. + +### How to Use Plugins + +opencode supports plugins for extended workflows. +[oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) adds +multi-agent orchestration, model routing, and specialized skills — the entire +plugin system fits in a single config line: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["oh-my-opencode@latest"], + "provider": { + "anthropic": {} + } +} +``` + +That's it. One plugin, your providers, done. The plugin handles agent +definitions, skill loading, and model routing automatically. + +### How to Use with Local Models + +Install [ollama](../ollama/) (also available via webi), then configure opencode: + +```sh +webi ollama +ollama serve & +ollama pull qwen2.5-coder:14b +``` + +```json +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "options": { + "baseURL": "http://127.0.0.1:11434/v1" + }, + "models": { + "qwen2.5-coder:14b": { + "name": "Qwen 2.5 Coder 14B (local)" + } + } + } + } +} +``` + +### Useful Key Bindings + +| Key | Action | +| -------- | -------------------------------- | +| `Enter` | Send message | +| `Ctrl+E` | Open editor for multi-line input | +| `Ctrl+C` | Cancel current operation | +| `Ctrl+L` | Clear screen | +| `/` | Slash commands | diff --git a/opencode/SKILL.md b/opencode/SKILL.md new file mode 100644 index 000000000..9a8fabd49 --- /dev/null +++ b/opencode/SKILL.md @@ -0,0 +1,124 @@ +--- +name: opencode +description: + Terminal-based AI coding agent with multi-provider LLM support, file editing, + shell access, and plugin system. Use when the user wants AI pair programming + in the terminal. +homepage: https://github.com/anomalyco/opencode +--- + +# OpenCode + +Terminal-based AI coding agent that connects to multiple LLM providers +(Anthropic, OpenAI, Google, local Ollama) with an interactive TUI for writing, +reviewing, and refactoring code. + +## When to Use + +- User wants AI pair programming directly in the terminal +- User needs full tool use (file editing, shell commands, grep, read) +- User wants plugin-based multi-agent orchestration (oh-my-opencode) +- User wants local-first AI coding with Ollama (no API costs) + +## Installation + +```sh +curl https://webi.sh/opencode | sh +source ~/.config/envman/PATH.env +``` + +## Quick Start + +1. **Set API key**: + + ```sh + export ANTHROPIC_API_KEY="sk-ant-..." + ``` + +2. **Launch in project directory**: + + ```sh + cd ~/your-project + opencode + ``` + +## Configuration + +Edit `~/.config/opencode/opencode.json`: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "anthropic": {}, + "openai": {} + }, + "model": { + "big": "anthropic/claude-sonnet-4-5-20250514", + "small": "anthropic/claude-haiku-4-5-20250514" + } +} +``` + +### With oh-my-opencode Plugin + +```json +{ + "$schema": "https://opencode.ai/config.json", + "plugin": ["oh-my-opencode@latest"], + "provider": { + "anthropic": {} + } +} +``` + +### Local Models with Ollama + +```sh +webi ollama +ollama serve & +ollama pull qwen2.5-coder:14b +``` + +```json +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama": { + "npm": "@ai-sdk/openai-compatible", + "options": { + "baseURL": "http://127.0.0.1:11434/v1" + }, + "models": { + "qwen2.5-coder:14b": { + "name": "Qwen 2.5 Coder 14B (local)" + } + } + } + } +} +``` + +## Key Bindings + +| Key | Action | +| -------- | -------------------------------- | +| `Enter` | Send message | +| `Ctrl+E` | Open editor for multi-line input | +| `Ctrl+C` | Cancel current operation | +| `Ctrl+L` | Clear screen | +| `/` | Slash commands | + +## Files Created + +```text +~/.config/envman/PATH.env +~/.local/bin/opencode +~/.local/opt/opencode-VERSION/bin/opencode +~/.config/opencode/opencode.json +``` + +## Related Webi Installers + +- `ollama` — Local LLM server for offline AI coding +- `node` — Required for installing plugins (oh-my-opencode) diff --git a/opencode/install.ps1 b/opencode/install.ps1 new file mode 100644 index 000000000..97b505921 --- /dev/null +++ b/opencode/install.ps1 @@ -0,0 +1,53 @@ +#!/usr/bin/env pwsh + +#################### +# Install opencode # +#################### + +# Every package should define these variables +$pkg_cmd_name = "opencode" + +$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\opencode.exe" +$pkg_dst = "$pkg_dst_cmd" + +$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\opencode-v$Env:WEBI_VERSION\bin\opencode.exe" +$pkg_src_bin = "$Env:USERPROFILE\.local\opt\opencode-v$Env:WEBI_VERSION\bin" +$pkg_src_dir = "$Env:USERPROFILE\.local\opt\opencode-v$Env:WEBI_VERSION" +$pkg_src = "$pkg_src_cmd" + +New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | Out-Null +$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE" + +# Fetch archive +if (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) { + Write-Output "Downloading opencode from $Env:WEBI_PKG_URL to $pkg_download" + & curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part" + & Move-Item "$pkg_download.part" "$pkg_download" +} + +if (!(Test-Path -Path "$pkg_src_cmd")) { + Write-Output "Installing opencode" + + # Enter tmp + Push-Location .local\tmp + + # Remove any leftover tmp cruft + Remove-Item -Path ".\opencode-v*" -Recurse -ErrorAction Ignore + Remove-Item -Path ".\opencode.exe" -Recurse -ErrorAction Ignore + + # Unpack archive + Write-Output "Unpacking $pkg_download" + & tar xf "$pkg_download" + + # Move single binary into place + Write-Output "Install Location: $pkg_src_cmd" + New-Item "$pkg_src_bin" -ItemType Directory -Force | Out-Null + Move-Item -Path ".\opencode.exe" -Destination "$pkg_src_bin" + + # Exit tmp + Pop-Location +} + +Write-Output "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'" +Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | Out-Null +Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse diff --git a/opencode/install.sh b/opencode/install.sh new file mode 100644 index 000000000..c75e48045 --- /dev/null +++ b/opencode/install.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# shellcheck disable=SC2034 + +set -e +set -u + +__init_opencode() { + + #################### + # Install opencode # + #################### + + pkg_cmd_name="opencode" + + pkg_dst_cmd="$HOME/.local/bin/opencode" + pkg_dst="$pkg_dst_cmd" + + pkg_src_cmd="$HOME/.local/opt/opencode-v$WEBI_VERSION/bin/opencode" + pkg_src_dir="$HOME/.local/opt/opencode-v$WEBI_VERSION" + pkg_src="$pkg_src_cmd" + + pkg_install() { + # ~/.local/opt/opencode-v1.2.27/bin/ + mkdir -p "$(dirname "$pkg_src_cmd")" + + # mv ./opencode ~/.local/opt/opencode-v1.2.27/bin/opencode + mv ./opencode "$pkg_src_cmd" + chmod a+x "$pkg_src_cmd" + } + + pkg_get_current_version() { + # 'opencode --version' outputs just the version number: + # 1.2.27 + opencode --version 2> /dev/null | + head -n 1 + } + +} + +__init_opencode diff --git a/opencode/releases.js b/opencode/releases.js new file mode 100644 index 000000000..ff2c0670d --- /dev/null +++ b/opencode/releases.js @@ -0,0 +1,44 @@ +'use strict'; + +var github = require('../_common/github.js'); +var owner = 'anomalyco'; +var repo = 'opencode'; + +let Releases = module.exports; + +Releases.latest = async function () { + let all = await github(null, owner, repo); + + // Keep only CLI binaries: opencode-{os}-{arch}.{tar.gz|zip} + // Exclude: desktop/electron apps, baseline builds, .yml/.yaml manifests, + // .json metadata, .dmg/.deb/.rpm packages, .sig signatures + // Exclude musl builds: the normalizer maps both musl and gnu to the same + // os/arch key, causing duplicates. Prefer gnu (glibc) as the default. + all.releases = all.releases.filter(function (rel) { + let name = rel.name; + return ( + name.match(/^opencode-(darwin|linux|windows)-/) && + !name.includes('desktop') && + !name.includes('baseline') && + !name.includes('-musl') && + (name.endsWith('.tar.gz') || name.endsWith('.zip')) + ); + }); + + return all; +}; + +Releases.sample = async function () { + let normalize = require('../_webi/normalize.js'); + let all = await Releases.latest(); + all = normalize(all); + all.releases = all.releases.slice(0, 10); + return all; +}; + +if (module === require.main) { + (async function () { + let samples = await Releases.sample(); + console.info(JSON.stringify(samples, null, 2)); + })(); +} diff --git a/test/install.sh b/test/install.sh index 7e0b4bcb7..68672bb40 100644 --- a/test/install.sh +++ b/test/install.sh @@ -55,6 +55,7 @@ __rmrf_local() { nerd-font \ nerdfont \ node \ + opencode \ ots \ pandoc \ pathman \ @@ -151,6 +152,7 @@ __rmrf_local() { nerd-font \ nerdfont \ node \ + opencode \ ots \ pandoc \ pathman \