Files
Hermes Agent ccc63d1e70 first commit
2026-05-10 13:52:46 +08:00

319 lines
10 KiB
Markdown

---
name: opencode
description: "Delegate coding to OpenCode CLI (features, PR review)."
version: 1.3.0
author: Hermes Agent
license: MIT
metadata:
hermes:
tags: [Coding-Agent, OpenCode, Autonomous, Refactoring, Code-Review]
related_skills: [claude-code, codex, hermes-agent]
---
# OpenCode CLI
Use [OpenCode](https://opencode.ai) as an autonomous coding worker orchestrated by Hermes terminal/process tools. OpenCode is a provider-agnostic, open-source AI coding agent with a TUI and CLI.
## When to Use
- User explicitly asks to use OpenCode
- You want an external coding agent to implement/refactor/review code
- You need long-running coding sessions with progress checks
- You want parallel task execution in isolated workdirs/worktrees
## Prerequisites
- OpenCode installed: `npm i -g opencode-ai@latest` or `brew install anomalyco/tap/opencode`
- Auth configured: `opencode auth login` or set provider env vars (OPENROUTER_API_KEY, etc.)
- Verify: `opencode auth list` should show at least one provider
- Git repository for code tasks (recommended)
- `pty=true` for interactive TUI sessions
## Installation (Important)
`npm i -g opencode-ai@latest` may fail due to permissions. Use `--prefix ~/.local` instead:
```
npm i -g opencode-ai@latest --prefix ~/.local
export PATH="$HOME/.local/bin:$PATH"
opencode --version
```
The binary resolves to `~/.local/bin/opencode`.
## Binary Resolution (Important)
Shell environments may resolve different OpenCode binaries. If behavior differs between your terminal and Hermes, check:
```
terminal(command="which -a opencode")
terminal(command="opencode --version")
```
If needed, pin an explicit binary path:
```
terminal(command="$HOME/.local/bin/opencode run '...'")
```
## Headless Server Mode
Start a long-running OpenCode server accessible via web browser or CLI attach:
```
export PATH="$HOME/.local/bin:$PATH"
opencode serve --port 8090 --hostname 0.0.0.0 --print-logs
```
**Important flags:**
| Flag | Purpose |
|------|---------|
| `--port` | Port to listen on (default: random) |
| `--hostname` | Bind address (default: 127.0.0.1) |
| `--print-logs` | Output server logs to stderr |
| `--cors` | Additional CORS domains (array) |
| `--mdns` | Enable mDNS discovery (auto-sets hostname to 0.0.0.0) |
| `--mdns-domain` | Custom mDNS domain (default: opencode.local) |
| `--pure` | Run without external plugins |
### Server Authentication
Uses HTTP Basic Auth. **Username is always `opencode` (cannot be changed)**. Password set via env var:
```bash
OPENCODE_SERVER_PASSWORD="your_password" opencode serve --port 8090
```
Browser access: `http://opencode:your_password@your-server-ip:8090`
Or just visit `http://your-server-ip:8090` and enter credentials in the popup dialog.
### Deploy to Custom Directory (e.g. /www/wwwroot/opencode)
```bash
sudo mkdir -p /www/wwwroot/opencode
sudo chown -R $(whoami):$(whoami) /www/wwwroot/opencode
npm i -g opencode-ai@latest --prefix /www/wwwroot/opencode
sudo ln -s /www/wwwroot/opencode/bin/opencode /usr/local/bin/opencode
```
### 宝塔面板 (BT Panel) Deployment
Use **Node项目** type with these fields:
| Field | Value |
|-------|-------|
| 项目名称 | OpenCode |
| 项目路径 | `/www/wwwroot/opencode` |
| 启动命令 | `node /www/wwwroot/opencode/bin/opencode serve --port 8090 --hostname 127.0.0.1` |
| 端口 | `8090` |
Add environment variable: `OPENCODE_SERVER_PASSWORD` = your password.
### Nginx Reverse Proxy (for domain access)
Configure in 宝塔 or nginx.conf:
| Field | Value |
|-------|-------|
| 域名 | `opencode.ephron.ren` |
| 目标 | `http://127.0.0.1:8090` |
| 发送域名(host) | `$host` or `$http_host` (either works) |
Then access via `http://opencode.ephron.ren` with HTTP Basic Auth credentials.
### Attach from CLI
```bash
export OPENCODE_SERVER_URL="http://127.0.0.1:8090"
export OPENCODE_SERVER_PASSWORD="your_password"
opencode --attach http://127.0.0.1:8090
```
Note: `--attach` requires a full HTTP URL, not just a hostname.
**Access via browser:** The server serves a full Web TUI at the HTTP URL.
**Verify server is running:**
```bash
curl -s http://127.0.0.1:8090/ # Returns HTML
# Check logs for "server listening on http://..."
```
## One-Shot Tasks
Use `opencode run` for bounded, non-interactive tasks:
```
terminal(command="opencode run 'Add retry logic to API calls and update tests'", workdir="~/project")
```
Attach context files with `-f`:
```
terminal(command="opencode run 'Review this config for security issues' -f config.yaml -f .env.example", workdir="~/project")
```
Show model thinking with `--thinking`:
```
terminal(command="opencode run 'Debug why tests fail in CI' --thinking", workdir="~/project")
```
Force a specific model:
```
terminal(command="opencode run 'Refactor auth module' --model openrouter/anthropic/claude-sonnet-4", workdir="~/project")
```
## Interactive Sessions (Background)
For iterative work requiring multiple exchanges, start the TUI in background:
```
terminal(command="opencode", workdir="~/project", background=true, pty=true)
# Returns session_id
# Send a prompt
process(action="submit", session_id="<id>", data="Implement OAuth refresh flow and add tests")
# Monitor progress
process(action="poll", session_id="<id>")
process(action="log", session_id="<id>")
# Send follow-up input
process(action="submit", session_id="<id>", data="Now add error handling for token expiry")
# Exit cleanly — Ctrl+C
process(action="write", session_id="<id>", data="\x03")
# Or just kill the process
process(action="kill", session_id="<id>")
```
**Important:** Do NOT use `/exit` — it is not a valid OpenCode command and will open an agent selector dialog instead. Use Ctrl+C (`\x03`) or `process(action="kill")` to exit.
### TUI Keybindings
| Key | Action |
|-----|--------|
| `Enter` | Submit message (press twice if needed) |
| `Tab` | Switch between agents (build/plan) |
| `Ctrl+P` | Open command palette |
| `Ctrl+X L` | Switch session |
| `Ctrl+X M` | Switch model |
| `Ctrl+X N` | New session |
| `Ctrl+X E` | Open editor |
| `Ctrl+C` | Exit OpenCode |
### Resuming Sessions
After exiting, OpenCode prints a session ID. Resume with:
```
terminal(command="opencode -c", workdir="~/project", background=true, pty=true) # Continue last session
terminal(command="opencode -s ses_abc123", workdir="~/project", background=true, pty=true) # Specific session
```
## Common Flags
| Flag | Use |
|------|-----|
| `run 'prompt'` | One-shot execution and exit |
| `--continue` / `-c` | Continue the last OpenCode session |
| `--session <id>` / `-s` | Continue a specific session |
| `--agent <name>` | Choose OpenCode agent (build or plan) |
| `--model provider/model` | Force specific model |
| `--format json` | Machine-readable output/events |
| `--file <path>` / `-f` | Attach file(s) to the message |
| `--thinking` | Show model thinking blocks |
| `--variant <level>` | Reasoning effort (high, max, minimal) |
| `--title <name>` | Name the session |
| `--attach <url>` | Connect to a running opencode server (full HTTP URL, e.g. `http://127.0.0.1:8090`) |
## Procedure
1. Verify tool readiness:
- `terminal(command="opencode --version")`
- `terminal(command="opencode auth list")`
2. For bounded tasks, use `opencode run '...'` (no pty needed).
3. For iterative tasks, start `opencode` with `background=true, pty=true`.
4. Monitor long tasks with `process(action="poll"|"log")`.
5. If OpenCode asks for input, respond via `process(action="submit", ...)`.
6. Exit with `process(action="write", data="\x03")` or `process(action="kill")`.
7. Summarize file changes, test results, and next steps back to user.
## PR Review Workflow
OpenCode has a built-in PR command:
```
terminal(command="opencode pr 42", workdir="~/project", pty=true)
```
Or review in a temporary clone for isolation:
```
terminal(command="REVIEW=$(mktemp -d) && git clone https://github.com/user/repo.git $REVIEW && cd $REVIEW && opencode run 'Review this PR vs main. Report bugs, security risks, test gaps, and style issues.' -f $(git diff origin/main --name-only | head -20 | tr '\n' ' ')", pty=true)
```
## Parallel Work Pattern
Use separate workdirs/worktrees to avoid collisions:
```
terminal(command="opencode run 'Fix issue #101 and commit'", workdir="/tmp/issue-101", background=true, pty=true)
terminal(command="opencode run 'Add parser regression tests and commit'", workdir="/tmp/issue-102", background=true, pty=true)
process(action="list")
```
## Session & Cost Management
List past sessions:
```
terminal(command="opencode session list")
```
Check token usage and costs:
```
terminal(command="opencode stats")
terminal(command="opencode stats --days 7 --models anthropic/claude-sonnet-4")
```
## Pitfalls
- Interactive `opencode` (TUI) sessions require `pty=true`. The `opencode run` command does NOT need pty.
- `/exit` is NOT a valid command — it opens an agent selector. Use Ctrl+C to exit the TUI.
- PATH mismatch can select the wrong OpenCode binary/model config.
- If OpenCode appears stuck, inspect logs before killing:
- `process(action="log", session_id="<id>")`
- Avoid sharing one working directory across parallel OpenCode sessions.
- Enter may need to be pressed twice to submit in the TUI (once to finalize text, once to send).
- `npm i -g` fails on some environments — use `npm i -g --prefix ~/.local` and `export PATH="$HOME/.local/bin:$PATH"`.
- `--attach <url>` requires a full HTTP URL (e.g. `http://127.0.0.1:8090`), not just a hostname.
- Server mode has no authentication by default — set `OPENCODE_SERVER_PASSWORD` env var before starting the server if needed.
- `opencode run` vs `--attach`: `run` creates a new session and exits; `--attach` connects to an existing server session. Using `opencode run` against a server URL returns "Session not found" — use `--attach` for server mode.
- When killed, the server process logs `tcsetattr: Inappropriate ioctl for device` — this is harmless, just the PTY cleanup noise.
## Verification
Smoke test:
```
terminal(command="opencode run 'Respond with exactly: OPENCODE_SMOKE_OK'")
```
Success criteria:
- Output includes `OPENCODE_SMOKE_OK`
- Command exits without provider/model errors
- For code tasks: expected files changed and tests pass
## Rules
1. Prefer `opencode run` for one-shot automation — it's simpler and doesn't need pty.
2. Use interactive background mode only when iteration is needed.
3. Always scope OpenCode sessions to a single repo/workdir.
4. For long tasks, provide progress updates from `process` logs.
5. Report concrete outcomes (files changed, tests, remaining risks).
6. Exit interactive sessions with Ctrl+C or kill, never `/exit`.