commit 40c4d63b808221752fce07f3c2c4af08d09dc69b Author: fez5587 Date: Tue Mar 31 18:24:37 2026 -0400 Add portable OpenCode config bundle for Linux and Windows diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..626ca05 --- /dev/null +++ b/.env.example @@ -0,0 +1,9 @@ +# Copy to .env and fill locally. Never commit your real keys. + +OPENROUTER_API_KEY= +OPENCODE_ZEN_API_KEY= +V0_API_KEY= +GITHUB_TOKEN= +ANTHROPIC_API_KEY= +OPENAI_API_KEY= +GOOGLE_API_KEY= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc714e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +*.env +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..77aab25 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# OpenCode Portable Config + +This folder is safe to commit to GitHub. It contains config and installers, but no API keys. + +## What is included + +- `templates/opencode.json` +- `templates/oh-my-opencode.json` +- `scripts/install-linux.sh` +- `scripts/install-windows.ps1` +- `.env.example` + +## How to use + +1. Push this folder to your GitHub repo. +2. On a target machine, clone or download the repo. +3. Run the platform installer from `scripts/`. +4. Copy `.env.example` to `.env` and fill keys locally. +5. Run `opencode auth login ` or `/connect` in OpenCode. + +## Important + +- Do not commit `.env`. +- Do not commit `~/.local/share/opencode/auth.json`. +- Credentials should always be entered locally on each machine. diff --git a/scripts/install-linux.sh b/scripts/install-linux.sh new file mode 100755 index 0000000..08f8803 --- /dev/null +++ b/scripts/install-linux.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +TEMPLATES_DIR="$ROOT_DIR/templates" +TARGET_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/opencode" + +echo "Installing OpenCode config to: $TARGET_DIR" +mkdir -p "$TARGET_DIR" +cp "$TEMPLATES_DIR/opencode.json" "$TARGET_DIR/opencode.json" +cp "$TEMPLATES_DIR/oh-my-opencode.json" "$TARGET_DIR/oh-my-opencode.json" + +echo "Installing optional components (Node/Bun packages)..." +if command -v bun >/dev/null 2>&1; then + (cd "$TARGET_DIR" && bun add @opencode-ai/plugin @code-yeongyu/comment-checker) +elif command -v npm >/dev/null 2>&1; then + (cd "$TARGET_DIR" && npm install @opencode-ai/plugin @code-yeongyu/comment-checker) +else + echo "Skipping package install: bun/npm not found" +fi + +echo "Done." +echo "Next steps:" +echo "1) Add keys locally with: opencode auth login " +echo "2) Verify with: bunx oh-my-opencode doctor --verbose" diff --git a/scripts/install-windows.ps1 b/scripts/install-windows.ps1 new file mode 100644 index 0000000..b11bfe7 --- /dev/null +++ b/scripts/install-windows.ps1 @@ -0,0 +1,28 @@ +$ErrorActionPreference = "Stop" + +$RootDir = Split-Path -Path (Split-Path -Parent $MyInvocation.MyCommand.Path) -Parent +$TemplatesDir = Join-Path $RootDir "templates" +$TargetDir = Join-Path $env:USERPROFILE ".config\opencode" + +Write-Host "Installing OpenCode config to: $TargetDir" +New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null +Copy-Item (Join-Path $TemplatesDir "opencode.json") (Join-Path $TargetDir "opencode.json") -Force +Copy-Item (Join-Path $TemplatesDir "oh-my-opencode.json") (Join-Path $TargetDir "oh-my-opencode.json") -Force + +Write-Host "Installing optional components (Node/Bun packages)..." +if (Get-Command bun -ErrorAction SilentlyContinue) { + Push-Location $TargetDir + bun add @opencode-ai/plugin @code-yeongyu/comment-checker + Pop-Location +} elseif (Get-Command npm -ErrorAction SilentlyContinue) { + Push-Location $TargetDir + npm install @opencode-ai/plugin @code-yeongyu/comment-checker + Pop-Location +} else { + Write-Host "Skipping package install: bun/npm not found" +} + +Write-Host "Done." +Write-Host "Next steps:" +Write-Host "1) Add keys locally with: opencode auth login " +Write-Host "2) Verify with: bunx oh-my-opencode doctor --verbose" diff --git a/templates/oh-my-opencode.json b/templates/oh-my-opencode.json new file mode 100644 index 0000000..95fb925 --- /dev/null +++ b/templates/oh-my-opencode.json @@ -0,0 +1,221 @@ +{ + "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/dev/assets/oh-my-opencode.schema.json", + "agents": { + "sisyphus": { + "model": "zai-coding-plan/glm-4.7-flashx", + "variant": "medium", + "fallback_models": [ + "github-copilot/gpt-5-mini", + "opencode-go/glm-5", + "v0/v0-pro", + "openrouter/nvidia/nemotron-3-super-120b-a12b:free" + ] + }, + "hephaestus": { + "model": "opencode-go/glm-5", + "variant": "medium", + "fallback_models": [ + "github-copilot/grok-code-fast-1", + "zai-coding-plan/glm-4.7-flash", + "openrouter/stepfun/step-3.5-flash:free", + "v0/v0-mini" + ] + }, + "oracle": { + "model": "github-copilot/gpt-5-mini", + "variant": "medium", + "fallback_models": [ + "anthropic/claude-sonnet-4-6", + "zai-coding-plan/glm-4.6", + "v0/v0-pro", + "openrouter/nvidia/nemotron-nano-12b-v2-vl:free" + ] + }, + "librarian": { + "model": "openrouter/stepfun/step-3.5-flash:free", + "fallback_models": [ + "google/gemini-3-flash-preview", + "github-copilot/gpt-5-mini", + "v0/v0-mini", + "anthropic/claude-sonnet-4-6" + ] + }, + "explore": { + "model": "v0/v0-mini", + "fallback_models": [ + "openrouter/nvidia/nemotron-nano-12b-v2-vl:free", + "github-copilot/grok-code-fast-1", + "zai-coding-plan/glm-4.7-flash", + "opencode-go/kimi-k2.5" + ] + }, + "multimodal-looker": { + "model": "zai-coding-plan/glm-4.6v", + "fallback_models": [ + "openrouter/nvidia/nemotron-nano-12b-v2-vl:free", + "google/gemini-3.1-pro-preview", + "opencode/gpt-5.4" + ] + }, + "prometheus": { + "model": "openai/gpt-5.4", + "variant": "medium", + "fallback_models": [ + "anthropic/claude-opus-4-6", + "github-copilot/gpt-5.4", + "zai-coding-plan/glm-4.7-flashx", + "v0/v0-pro" + ] + }, + "metis": { + "model": "opencode/gpt-5.4", + "variant": "medium", + "fallback_models": [ + "google/gemini-3.1-pro-preview", + "anthropic/claude-opus-4-6", + "openrouter/nvidia/nemotron-3-super-120b-a12b:free", + "github-copilot/gpt-5-mini" + ] + }, + "momus": { + "model": "anthropic/claude-sonnet-4-6", + "variant": "medium", + "fallback_models": [ + "openai/gpt-5.4", + "github-copilot/gpt-5-mini", + "openrouter/stepfun/step-3.5-flash:free", + "v0/v0-pro" + ] + }, + "atlas": { + "model": "github-copilot/grok-code-fast-1", + "fallback_models": [ + "openrouter/stepfun/step-3.5-flash:free", + "zai-coding-plan/glm-4.7-flash", + "opencode-go/kimi-k2.5", + "anthropic/claude-sonnet-4-6" + ] + } + }, + "background_task": { + "defaultConcurrency": 12, + "providerConcurrency": { + "anthropic": 1, + "openai": 1, + "google": 1, + "github-copilot": 2, + "zai-coding-plan": 2, + "opencode": 1, + "v0": 2, + "opencode-go": 2, + "openrouter": 3 + }, + "modelConcurrency": { + "openai/gpt-5.4": 1, + "openai/gpt-5.2": 1, + "anthropic/claude-opus-4-6": 1, + "anthropic/claude-sonnet-4-6": 1, + "google/gemini-3-flash-preview": 1, + "google/gemini-3.1-pro-preview": 1, + "github-copilot/gpt-5.3-codex": 1, + "github-copilot/gpt-5.4": 1, + "github-copilot/gpt-5-mini": 2, + "github-copilot/grok-code-fast-1": 2, + "zai-coding-plan/glm-4.6v": 1, + "zai-coding-plan/glm-4.7-flash": 2, + "zai-coding-plan/glm-4.7-flashx": 2, + "zai-coding-plan/glm-4.6": 2, + "opencode/gpt-5.3-codex": 1, + "opencode/gpt-5.4": 1, + "v0/v0-pro": 2, + "v0/v0-mini": 2, + "opencode-go/glm-5": 2, + "opencode-go/kimi-k2.5": 2, + "openrouter/nvidia/nemotron-3-super-120b-a12b:free": 3, + "openrouter/stepfun/step-3.5-flash:free": 3, + "openrouter/nvidia/nemotron-nano-12b-v2-vl:free": 3 + } + }, + "model_fallback": true, + "runtime_fallback": false, + "categories": { + "visual-engineering": { + "model": "google/gemini-3.1-pro-preview", + "variant": "high", + "fallback_models": [ + "openrouter/nvidia/nemotron-nano-12b-v2-vl:free", + "zai-coding-plan/glm-4.6v", + "openai/gpt-5.4" + ] + }, + "ultrabrain": { + "model": "zai-coding-plan/glm-4.7-flashx", + "variant": "high", + "fallback_models": [ + "opencode-go/glm-5", + "github-copilot/gpt-5-mini", + "anthropic/claude-opus-4-6", + "v0/v0-pro" + ] + }, + "deep": { + "model": "anthropic/claude-opus-4-6", + "variant": "medium", + "fallback_models": [ + "openai/gpt-5.4", + "zai-coding-plan/glm-4.6", + "openrouter/nvidia/nemotron-3-super-120b-a12b:free" + ] + }, + "artistry": { + "model": "github-copilot/gpt-5.4", + "variant": "high", + "fallback_models": [ + "google/gemini-3-flash-preview", + "openrouter/stepfun/step-3.5-flash:free", + "v0/v0-pro" + ] + }, + "quick": { + "model": "opencode-go/glm-5", + "variant": "medium", + "fallback_models": [ + "zai-coding-plan/glm-4.7-flash", + "github-copilot/grok-code-fast-1", + "v0/v0-mini", + "openrouter/stepfun/step-3.5-flash:free" + ] + }, + "unspecified-low": { + "model": "openrouter/stepfun/step-3.5-flash:free", + "variant": "medium", + "fallback_models": [ + "v0/v0-mini", + "zai-coding-plan/glm-4.6", + "github-copilot/gpt-5-mini", + "google/gemini-3-flash-preview" + ] + }, + "unspecified-high": { + "model": "github-copilot/gpt-5.3-codex", + "variant": "high", + "fallback_models": [ + "openai/gpt-5.4", + "anthropic/claude-sonnet-4-6", + "zai-coding-plan/glm-4.7-flashx" + ] + }, + "writing": { + "model": "anthropic/claude-sonnet-4-6", + "variant": "medium", + "fallback_models": [ + "openai/gpt-5.4", + "github-copilot/gpt-5-mini", + "v0/v0-pro" + ] + } + }, + "_migrations": [ + "model-version:anthropic/claude-sonnet-4-5->anthropic/claude-sonnet-4-6" + ] +} diff --git a/templates/opencode.json b/templates/opencode.json new file mode 100644 index 0000000..1e9b818 --- /dev/null +++ b/templates/opencode.json @@ -0,0 +1,139 @@ +{ + "$schema": "https://opencode.ai/config.json", + "provider": { + "ollama2": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama 2 (main local)", + "options": { + "baseURL": "http://127.0.0.1:11434/v1", + "apiKey": "ollama", + "timeout": false, + "requestTimeout": 900000, + "chunkTimeout": 180000 + }, + "models": { + "devstral-small-2": { + "name": "Devstral Small 2" + }, + "qwen2.5-coder:7b": { + "name": "Qwen 2.5 Coder (7B)" + } + } + }, + "ollama3": { + "npm": "@ai-sdk/openai-compatible", + "name": "Ollama 3 (12GB local)", + "options": { + "baseURL": "http://127.0.0.1:30069/v1", + "apiKey": "ollama", + "timeout": false, + "requestTimeout": 900000, + "chunkTimeout": 180000 + }, + "models": { + "qwen2.5-coder:7b": { + "name": "Qwen 2.5 Coder (7B)" + } + } + }, + "anthropic": { + "npm": "@ai-sdk/openai-compatible", + "name": "Anthropic", + "options": { + "baseURL": "https://api.anthropic.com/v1" + }, + "models": { + "claude-opus-4-6": { + "name": "Claude Opus 4.6" + } + } + }, + "github-copilot": { + "npm": "@ai-sdk/openai-compatible", + "name": "GitHub Copilot", + "models": { + "gpt-5-mini": { + "name": "GPT-5 Mini" + }, + "grok-code-fast-1": { + "name": "Grok Code Fast 1" + } + } + }, + "zai-coding-plan": { + "npm": "@ai-sdk/openai-compatible", + "name": "Z.AI Coding Plan", + "models": { + "glm-4.7-flash": { + "name": "GLM-4.7-Flash" + }, + "glm-4.7-flashx": { + "name": "GLM-4.7-Flashx" + }, + "glm-4.6": { + "name": "GLM-4.6" + } + } + }, + "v0": { + "npm": "@ai-sdk/openai-compatible", + "name": "v0 (Vercel)", + "options": { + "baseURL": "https://api.v0.dev/v1" + }, + "models": { + "v0-pro": { + "name": "v0 Pro" + }, + "v0-mini": { + "name": "v0 Mini" + } + } + }, + "openrouter": { + "npm": "@ai-sdk/openai-compatible", + "name": "OpenRouter", + "options": { + "baseURL": "https://openrouter.ai/api/v1" + }, + "models": { + "nvidia/nemotron-3-super-120b-a12b:free": { + "name": "NVIDIA Nemotron 3 Super 120B A12B (Free)" + }, + "stepfun/step-3.5-flash:free": { + "name": "StepFun Step 3.5 Flash (Free)" + }, + "nvidia/nemotron-nano-12b-v2-vl:free": { + "name": "NVIDIA Nemotron Nano 12B V2 VL (Free)" + } + } + }, + "opencode-zen": { + "npm": "@ai-sdk/openai-compatible", + "name": "OpenCode Zen", + "options": { + "baseURL": "https://opencode.ai/zen/v1" + }, + "models": { + "glm-5": { + "name": "GLM-5" + }, + "kimi-k2.5": { + "name": "Kimi K2.5" + } + } + } + }, + "permission": { + "read": "allow", + "edit": "allow", + "write": "allow", + "delete": "allow", + "execute": "allow" + }, + "model": "zai-coding-plan/glm-4.7-flashx", + "small_model": "github-copilot/gpt-5-mini", + "plugin": [ + "oh-my-opencode" + ] +}