diff --git a/opencode/README.md b/opencode/README.md index 9b7ea47..d4c7233 100644 --- a/opencode/README.md +++ b/opencode/README.md @@ -21,7 +21,6 @@ OpenCode is an open source AI coding agent. OPENCODE_PORT – default: 4096 OPENCODE_HOSTNAME – default: 0.0.0.0 - OLLAMA_HOST_URL – default: http://localhost:11434 ## Volume Notes @@ -29,8 +28,8 @@ With `VOL_PATH=/data`: | Container path | Host path | Purpose | |---|---|---| -| `/config` | `/data/opencode/config` | Config files (config.json) | -| `/data` | `/data/opencode/data` | OpenCode state | +| `/config` | `/data/opencode/config` | Config files (config.json), also `$HOME` | +| `/data` | `/data/opencode/data` | OpenCode state, incl. `auth.json` from `/connect` | | `/projects` | `/data/opencode/projects` | Workspace/project files | ## Network Notes @@ -52,41 +51,25 @@ See compose.yaml for the full set of environment variables. ## Additional Notes / Gotchas -Nothing specific to this stack so far. +This is a shared, reusable compose file — it ships "ready to use" but not +pre-authenticated. Whoever runs it needs to `/connect` a provider (OpenCode +Zen or OpenCode Go) before the agent can actually make model calls. Because +`HOME` and `XDG_DATA_HOME` point at the `/data` bind mount, that login +persists across container recreation. -## Dockhand Stack, Deploy from Git +### Config file -Cookbooks Repository -stackname: opencode -Compose file path: opencode/compose.yaml -Additional env file (optional): opencode/sample.env +The `config.json` at `opencode/config/config.json` is pre-configured to use +**OpenCode Zen** cloud models — no local model runtime required. Default +model is `opencode/deepseek-v4-flash-free` (free tier). -Then "Load" opencode/sample.env into the Environmental variables in dockhand. +Run `/connect` inside the TUI to authenticate with OpenCode Zen (or another +provider) and `/models` to switch. Login is persisted to the `/data` bind +mount, so it survives container recreation. -Create the Stack - -## Config file - -The `config.json` at `opencode/config/config.json` is pre-configured for -Ollama. Available models include: - -| Model | Default | Purpose | -|---|---|---| -| `qwen2.5-coder:14b` | default | Coding & agent tasks (recommended for this repo) | -| `qwen3:8b` / `qwen3:8b-16k` | | General purpose, tool support | -| `qwen2.5:7b` | | Lightweight general purpose | -| `mistral:latest` / `mistral-small3.2:latest` | | Chat & multilingual | -| `llama3.1:8b` | | General purpose | - -Tested on an NVIDIA GeForce RTX 5060 Ti (16 GB VRAM). - -## Model Guides - -See the `docs/` directory for best-practice guides on each supported model: - -- [DeepSeek V4 Flash Free](docs/DeepSeekV4FlashFree.md) — free model via opencode provider -- [Qwen3 8B 16k](docs/Qwen.md) — local model via Ollama -- [Claude (Anthropic)](docs/Claude.md) — paid model via API key +For a flat-rate bundle of open-source models instead of pay-as-you-go, see +**OpenCode Go** ($10/mo subscription, ~12 models including DeepSeek V4, +Qwen 3.6, GLM 5.2) — switch to it the same way via `/connect` and `/models`. To use a custom config with `VOL_PATH=/data`, copy it to: @@ -94,7 +77,14 @@ To use a custom config with `VOL_PATH=/data`, copy it to: /data/opencode/config/config.json ``` -## CLI Cheatsheet +### Model Guides + +See the `docs/` directory for best-practice guides on supported models: + +- [DeepSeek V4 Flash Free](docs/DeepSeekV4FlashFree.md) — free model via opencode provider (default) +- [Claude (Anthropic)](docs/Claude.md) — paid model via API key + +### CLI Cheatsheet From the `opencode/` directory, prefix commands with `docker compose`: @@ -130,16 +120,13 @@ docker compose exec opencode opencode upgrade /share # Create share link ``` -## Ollama +## Dockhand Stack, Deploy from Git -This stack requires the [ollama](../ollama/) stack to be running. The config -connects to `http://localhost:11434/v1` inside the container. +Cookbooks Repository +stackname: opencode +Compose file path: opencode/compose.yaml +Additional env file (optional): opencode/sample.env -To use a host-side ollama instead, set `OLLAMA_HOST=http://host.docker.internal:11434`. +Then "Load" opencode/sample.env into the Environmental variables in dockhand. -## Environment Variables - -- `OPENCODE_SERVER_PASSWORD` — required. Set a strong password for the web UI. -- `OLLAMA_HOST` — Ollama API endpoint (default `http://localhost:11434`) -- `OPENCODE_PORT` — Web UI port (default `4096`) -- `VOL_PATH` — Base path for persistent data (default `/data`) +Create the Stack diff --git a/opencode/compose.yaml b/opencode/compose.yaml index 2f9607b..5c669ae 100644 --- a/opencode/compose.yaml +++ b/opencode/compose.yaml @@ -4,13 +4,15 @@ services: restart: ${OPENCODE_RESTART:-unless-stopped} volumes: - ${VOL_PATH:-/data}/opencode/config:/config + - ${VOL_PATH:-/data}/opencode/data:/data - ${VOL_PROJECTS:-${VOL_PATH:-/data}/projects}:/projects environment: - OPENCODE_PORT=${OPENCODE_PORT:-4096} - OPENCODE_HOSTNAME=${OPENCODE_HOSTNAME:-0.0.0.0} - OPENCODE_CONFIG=/config/config.json - - OPENCODE_MODEL=qwen3:8b-16k - - OLLAMA_HOST=${OLLAMA_HOST_URL:-http://localhost:11434} + - OPENCODE_MODEL=opencode/deepseek-v4-flash-free + - HOME=/config + - XDG_DATA_HOME=/data ports: - ${OPENCODE_PORT:-4096}:4096 networks: diff --git a/opencode/config/config.json b/opencode/config/config.json index 283ca3e..f3a17ce 100644 --- a/opencode/config/config.json +++ b/opencode/config/config.json @@ -1,73 +1,14 @@ { "$schema": "https://opencode.ai/config.json", - "model": "ollama/qwen2.5-coder:14b", - "provider": { - "ollama": { - "npm": "@ai-sdk/openai-compatible", - "options": { - "baseURL": "http://localhost:11434/v1" - }, - "models": { - "qwen3:8b": { - "name": "Qwen3 8B", - "tools": true, - "limit": { - "context": 32768, - "output": 8192 - } - }, - "qwen3:8b-16k": { - "name": "Qwen3 8B (16k UI-Context)", - "tools": true, - "limit": { - "context": 16384, - "output": 8192 - } - }, - "qwen2.5:7b": { - "name": "Qwen2.5 7B", - "tools": true, - "limit": { - "context": 32768, - "output": 8192 - } - }, - "qwen2.5-coder:14b": { - "name": "Qwen2.5 Coder 14B", - "tools": true, - "limit": { - "context": 32768, - "output": 8192 - } - }, - "mistral:latest": { - "name": "Mistral 7B", - "tools": true, - "limit": { - "context": 32768, - "output": 4096 - } - }, - "mistral-small3.2:latest": { - "name": "Mistral Small 3.2", - "tools": true, - "limit": { - "context": 131072, - "output": 8192 - } - }, - "llama3.1:8b": { - "name": "Llama 3.1 8B", - "tools": true, - "limit": { - "context": 131072, - "output": 8192 - } - } - } - } + "model": "opencode/deepseek-v4-flash-free", + "tools": { + "bash": true }, "permission": { - "bash": { "git *": "ask" } + "bash": { + "*": "ask", + "git add *": "deny", + "git commit *": "deny" + } } -} \ No newline at end of file +} diff --git a/opencode/docs/Qwen.md b/opencode/docs/Qwen.md deleted file mode 100644 index 96844f6..0000000 --- a/opencode/docs/Qwen.md +++ /dev/null @@ -1,188 +0,0 @@ -# Qwen3 8B 16k — opencode Best Practices - -> **Reference:** [opencode Ollama docs](https://opencode.ai/docs/providers/#ollama) | [Ollama](https://ollama.com/) | [Qwen3](https://qwen.readthedocs.io/) - -## Quick Start (for new users) - -This project runs opencode in Docker with the web interface at `http://localhost:PORT`. - -- **Prerequisites:** Install [Ollama](https://ollama.com/download) and pull the model: `ollama pull qwen3:8b-16k` — ensure Ollama is running (`ollama serve`) -- **First run:** Use `/init` to generate an `AGENTS.md` — opencode analyzes your project structure, frameworks, and patterns, then writes a conventions file so future sessions know your code style, testing approach, naming conventions, and file organization -- **Undo:** Run `/undo` to revert the last change. Run it multiple times to undo further back. Use `/redo` to restore. All changes are tracked via git-style snapshots within the session. - -## Provider Configuration - -Reference: [Ollama provider docs](https://opencode.ai/docs/providers/#ollama) - -Ollama exposes an OpenAI-compatible API at `http://localhost:11434/v1`. Configure it in your `opencode.json`: - -```jsonc -{ - "$schema": "https://opencode.ai/config.json", - "provider": { - "ollama": { - "npm": "@ai-sdk/openai-compatible", - "name": "Ollama (local)", - "options": { - "baseURL": "http://localhost:11434/v1" - }, - "models": { - "qwen3:8b-16k": { - "name": "Qwen3 8B 16k", - "limit": { - "context": 16384, - "output": 4096 - } - } - } - } - }, - "model": "ollama/qwen3:8b-16k", - "permission": { - "edit": "ask", - "bash": "ask" - } -} -``` - -Permission values: `"allow"` (runs automatically), `"ask"` (prompts for approval), `"deny"` (disabled entirely). You can also use glob patterns for fine-grained control — e.g. `"grep *": "allow"`, `"git push": "ask"`. - -## Sample opencode.json - -Reference: [Config docs](https://opencode.ai/docs/config/) | [Permissions](https://opencode.ai/docs/permissions/) - -```jsonc -{ - "$schema": "https://opencode.ai/config.json", - "model": "ollama/qwen3:8b-16k", - "permission": { - "edit": "ask", - "bash": "ask" - } -} -``` - -## Local Model Considerations - -Qwen3 8B runs locally on your machine, which comes with trade-offs compared to a cloud API: - -- **Hardware:** ~8GB+ VRAM recommended. Runs on CPU via quantized variants (Q4/Q8) but slower -- **Performance:** Expect 10-40 tokens/second depending on your hardware and quantization -- **Context window:** 16k tokens — be concise in prompts and avoid dumping entire files -- **num_ctx:** If tool calls fail or the model seems confused, try increasing context: `ollama run qwen3:8b-16k --num-ctx 32768` -- **Tool calling:** Qwen3 has solid tool-calling support for a model its size, but may miss complex multi-tool workflows that larger models handle easily -- **No API key needed:** Everything runs locally — no data leaves your machine - -## Tools (Built-in) - -Reference: [Tools docs](https://opencode.ai/docs/tools/) - -Tools are functions the LLM can call to interact with your codebase — they're how opencode reads files, searches code, runs commands, and makes changes. Each tool has a specific purpose: - -- **`read`** — Read files. Prefer this over `bash cat` (structured output, line numbers). -- **`grep`** — Search file contents by regex. Faster and more targeted than `bash grep`. -- **`glob`** — Find files by pattern (e.g., `**/*.tsx`). Use instead of `bash find`. -- **`edit`** — Modify existing files via exact string replacement. Preferred for small changes. -- **`write`** — Create new files or overwrite existing ones. -- **`bash`** — Run arbitrary shell commands (git, npm, docker, etc.). -- **`skill`** — Load reusable instructions from a `SKILL.md` file. -- **`task`** — Delegate work to a subagent for parallel execution. -- **`webfetch`** / **`websearch`** — Fetch URLs or search the web (docs lookups, research). -- **`question`** — The agent asks you for clarification when instructions are ambiguous. - -## Custom Tools & MCP Servers - -Reference: [Custom Tools](https://opencode.ai/docs/custom-tools/) | [MCP Servers](https://opencode.ai/docs/mcp-servers/) - -- **Custom tools:** Place TypeScript files in `.opencode/tools/`. The filename becomes the tool name. Can invoke scripts in any language (Python, shell, etc.). -- **MCP** (**Model Context Protocol**) — an open standard for connecting LLMs to external tools and services. Configure MCP servers in `opencode.json` to give opencode access to databases, APIs, file systems, etc. - -```jsonc -// Example MCP server for a database -{ - "mcp": { - "my-db": { - "type": "stdio", - "command": "node", - "args": ["path/to/mcp-server.js"] - } - } -} -``` - -## Subagents - -Reference: [Agents docs](https://opencode.ai/docs/agents/) - -Invoke with `@name` in your prompt. Subagents run in separate sessions and can work in parallel: - -- **`@explore`** — Fast, read-only codebase explorer. *Use case:* "Find all places where the auth middleware is applied" — returns file paths and line numbers, no file changes. -- **`@general`** — Full subagent with all tools. *Use case:* "Refactor these three files in parallel" — fires multiple independent agents simultaneously, each handling one file. -- **`@scout`** — Read-only dependency researcher. Clones repos into a managed cache, inspects library source. - -**Example — refactoring with parallel subagents:** -> "Extract the validation logic from controllers into a shared middleware. -> @general handle /users, @general handle /orders, @general handle /products" - -Create custom subagents via `.opencode/agents/` (markdown files) or in `opencode.json`: - -```jsonc -{ - "agent": { - "review": { - "description": "Reviews code without making changes", - "mode": "subagent", - "permission": { "edit": "deny" }, - "model": "ollama/qwen3:8b-16k" - } - } -} -``` - -## Skills - -Reference: [Skills docs](https://opencode.ai/docs/skills/) - -Skills are reusable instruction files placed in `.opencode/skills//SKILL.md`. The agent sees them in the `skill` tool description and loads them on-demand when a task matches. - -```yaml ---- -name: git-release -description: Create consistent releases and changelogs ---- - -Instructions for creating releases... -``` - -## Permissions - -Reference: [Permissions docs](https://opencode.ai/docs/permissions/) - -Control tool access globally or per-agent: -- `"allow"` — runs without asking -- `"ask"` — prompts for approval -- `"deny"` — disabled entirely - -Permissions support glob patterns for fine-grained control over specific tools or commands. - -## AGENTS.md - -After running `/init`, opencode generates an `AGENTS.md` in your project root. This file captures your project's conventions and is read at the start of every session so the agent understands: -- Code style and naming conventions -- Framework and library choices -- Testing approach and commands -- File organization and patterns -- Any project-specific rules - -Keep it committed to git — it's the single source of truth for how the agent should behave in your project. - -## Prompting Tips (for Qwen3 8B) - -- **Context is precious at 16k.** Every token counts. Skip pleasantries — every "please", "thanks", or "could you" consumes space that could hold code or instructions. Prefer direct commands: *"Refactor this function"* not *"Could you please help me by refactoring this function?"* -- **Break complex tasks into smaller, single-responsibility steps** — the model handles focused prompts better than sprawling ones -- **Use Plan mode first** for multi-file changes, review the plan, then build -- **If the model loses track**, use `/undo` and rephrase more specifically with fewer instructions per message -- **Reference files with `@filename`** for fuzzy search -- **Avoid dumping entire large files** — use `read` with line ranges or grep for relevant sections -- **Prefer `edit` over `write`** for changes to existing files — smaller diffs are easier for the model to reason about -- **If tool calls fail**, increase Ollama's context window: `ollama run qwen3:8b-16k --num-ctx 32768` diff --git a/opencode/sample.env b/opencode/sample.env index 5feed45..3bdd58b 100644 --- a/opencode/sample.env +++ b/opencode/sample.env @@ -5,4 +5,3 @@ OPENCODE_IMAGE=ghcr.io/anomalyco/opencode:latest OPENCODE_RESTART=unless-stopped OPENCODE_PORT=4096 OPENCODE_HOSTNAME=0.0.0.0 -OLLAMA_HOST_URL=http://localhost:11434