opencode 自驱编程

运行

常用命令

https://opencode.ai/docs/zh-cn/cli/#session 

类型功能Ctrl+X之后按
运行web运行opencode web
参数也可以写到opencode.json
服务运行opencode serve --print-logs  --port 8080 --hostname 0.0.0.0 --log-level DEBUG
结束进程ps -ef | grep "opencode"
fuser -k 8080/tcp
CLI运行opencode /data/ai-project 
运行日志cd ~/.local/share/opencode/log/
tail -f $(ls -t ~/.local/share/opencode/log/*.log | head -1)
模型用量opencode stats
opencode stats --models 2>&1
opencode stats --days 7
opencode stats --models 5
  
管理私有库状态S
切换主题T
Session切换对话L
新对话N
对话命名Ctrl+R
聊天模式Tab  build和plan
聊天翻阅Shift+鼠标滚轮/PageUp
聊天跳转G
聊天悔棋U
对话列表opencode session list 2>&1 | head -30
对话导出opencode export ses_2832911b5ffewhSuGBWSGvL8k2 --format markdown > onepage.md
agent设置勾选Provider 
切换模型M
切换员工A
添加MCP 
   
   

组件增强

  • 静态文件
    • 项目配置:.opencode/skills/<name>/SKILL.md
    • 全局配置:~/.config/opencode/skills/<name>/SKILL.md
    • 项目 Claude 兼容:.claude/skills/<name>/SKILL.md
    • 全局 Claude 兼容:~/.claude/skills/<name>/SKILL.md
    • 项目代理兼容:.agents/skills/<name>/SKILL.md
    • 全局代理兼容:~/.agents/skills/<name>/SKILL.md

安装

官方推荐

  • https://opencode.ai/docs/rules/ 

    # YOLO
    curl -fsSL https://opencode.ai/install | bash
    
    # Package managers
    npm i -g opencode-ai@latest        		# or bun/pnpm/yarn
    scoop install opencode             		# Windows
    choco install opencode             		# Windows
    brew install anomalyco/tap/opencode 	# macOS and Linux (recommended, always up to date)
    brew install opencode              		# macOS and Linux (official brew formula, updated less)
    sudo pacman -S opencode            		# Arch Linux (Stable)
    paru -S opencode-bin               		# Arch Linux (Latest from AUR)
    mise use -g opencode               		# Any OS
    nix run nixpkgs#opencode           		# or github:anomalyco/opencode for latest dev branch

自制docker

  • dockerfile
  • build

    # -------------------- 单平台 ----------------------------
    docker build -t atibmcom/opencode:1.14.24 .
    
    # -------------------- 多平台 ----------------------------
    # 安装 QEMU 模拟器
    sudo apk add qemu-img qemu-system-arm qemu-system-aarch64 qemu-modules
    # 启用 buildx 实例
    docker buildx use default
    # 构建
    docker buildx build --platform linux/amd64,linux/arm64 -t atibmcom/opencode:1.14.24 .
  • 测试(生命周期和映射持久化)

    docker-compose up -d
    docker diff opencode | head -n 20 # 排查容器占用的原因
  • save/load image

    docker save atibmcom/opencode:1.14.29 | gzip > atibm-opencode-1.14.29.tar.gz
    docker load -i atibm-opencode-1.14.29.tar.gz
  • 清理

    # 清理已停止的容器;清理构建残留;清理无用的匿名卷;清理悬空镜像
    docker container prune -f;docker builder prune -f;docker system prune --volumes -f;docker image prune -f
  • 发布dockerhub

    docker login -u atibmcom
    docker push atibmcom/opencode:1.14.24
    docker tag atibmcom/opencode:1.14.24 atibmcom/opencode:latest

mint最小部署

  • 版本号

    curl -s https://api.github.com/repos/anomalyco/opencode/releases | jq -r '.[0:5] | .[] | .tag_name + " (" + .published_at + ")"'
    v1.4.6 (2026-04-15T07:26:50Z)
    v1.4.5 (2026-04-15T04:25:45Z)
    v1.4.4 (2026-04-15T00:04:10Z)
    v1.4.3 (2026-04-10T01:00:36Z)
    v1.4.2 (2026-04-09T16:25:08Z)
  • 安装

    curl -fsSL https://opencode.ai/install | bash -s -- -v 1.14.19
    opencode upgrade  # 升级
    opencode --version
    opencode  #启动进命令行
  • 配置
    • 配置文件:~/.config/opencode/opencode.json
      • 本地算力添加在这
    • 商业算力在web上输入key后,会在~/.local/share/opencode/auth.json自动写入,刷新页面就可以选择go模型了
    • 对话记录:~/.local/share/opencode/opencode.db
      • sqlite3 ~/.local/share/opencode/opencode.db "SELECT * FROM part ORDER BY time_created desc LIMIT 10"
    • 系统运行日志:~/.local/share/opencode/log
      • tail -f $(ls -t ~/.local/share/opencode/log/*.log | head -1)
  • 卸载

    (base) at@vm-mint:~$ opencode uninstall
    
                                       ▄
      █▀▀█ █▀▀█ █▀▀█ █▀▀▄ █▀▀▀ █▀▀█ █▀▀█ █▀▀█
      █  █ █  █ █▀▀▀ █  █ █    █  █ █  █ █▀▀▀
      ▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀
    
    ┌  Uninstall OpenCode
    │
    ●  Installation method: curl
    │
    │  The following will be removed:
    │
    ●    ✓ Data: ~/.local/share/opencode (33.7 MB)
    │
    ●    ✓ Cache: ~/.cache/opencode (26.1 MB)
    │
    ●    ✓ Config: ~/.config/opencode (4.3 MB)
    │
    ●    ✓ State: ~/.local/state/opencode (12.7 KB)
    │
    ●    ✓ Binary: ~/.opencode/bin/opencode
    │
    ●    ✓ Shell PATH in ~/.bashrc
    │
    ◆  Are you sure you want to uninstall?
    │  ○ Yes / ● No

常见问题

  • Assistant response prefill is incompatible with enable_thinking.

    简单来说,Opencode 在为了保证 AI 输出格式正确(例如强制要求输出 JSON),通常会预先给 AI 一个开头(比如 {),这被称为 Assistant Prefill。而当开启 enable_thinking 时,模型必须先输出一段 <thought> 标签包裹的内容,导致两者互斥。
    
    Thinking 模式的逻辑:当 enable_thinking 为 true 时,模型生成的首批 Token 必须是思考过程(Thinking block)。
    
    Opencode 的逻辑:为了让 AI 更加听话,Opencode 往往会在调用 API 时使用 assistant 角色预填一段文字(例如:{"plan":)。
    
    冲突点:API 无法同时处理“从预填的文字开始输出”和“从思考过程开始输出”。目前大多数兼容 OpenAI 的后端(如 vLLM, Ollama, 或某些中转站)都不支持这两者并存。
    ------------------llama.cpp最新版+chat jinja 好像已解决----------------

附件

opencode.json

# vi ~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "server": {
    "port": 8080,
    "hostname": "0.0.0.0"
  },
  "plugin": [
    "oh-my-openagent@latest"
  ],
  "autoupdate": false,
  "model": "v100-llama/Qwen3.5-27B",
  "small_model": "4060-lms/Qwen3.5-9B",
  "provider": {
    "4060-lms": {
      "name": "4060-lms",
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "apiKey": "xxxxxxxxxxxxx",
        "baseURL": "https://4060.atibm.com/v1"
      },
      "models": {
        "Qwen3.5-9B": {
          "name": "Qwen3.5-9B",
          "limit": {
            "context": 51200,
            "input": 30000,
            "output": 8192
          },
          "options": {
            "enable_thinking": false
          }
        }
      }
    },
    "v100-llama": {
      "name": "v100-llama",
      "npm": "@ai-sdk/openai-compatible",
      "options": {
        "apiKey": "xxxxxxxxxxxx",
        "baseURL": "https://v1008080.atibm.com/v1"
      },
      "models": {
        "Qwen3.5-27B": {
          "name": "Qwen3.5-27B",
          "limit": {
            "context": 102400,
            "input": 60000,
            "output": 8192
          },
          "options": {
            "enable_thinking": false
          }
        }
      }
    }
}

openchat.sh

#!/bin/bash
# cat ~/openchat.sh
# 检索对话记录的脚本,没抓取提问内容
DB="/home/at/.local/share/opencode/opencode.db"

# 只保留数字参数,默认5组
LIMIT="${1:-5}"

first_entry=1

# 查询 part 表,按时间正序输出
sqlite3 "$DB" "
SELECT data FROM part
ORDER BY time_created DESC
LIMIT $((LIMIT * 10))
" | tac | while read -r line; do

    # 思考内容
    if echo "$line" | grep -q '"type":"reasoning"'; then
        text=$(echo "$line" | python3 -c "import json,sys;o=json.load(sys.stdin);print(o.get('text',''))" 2>/dev/null)
        if [ -n "$text" ] && [ ${#text} -gt 5 ]; then
            if [ $first_entry -eq 1 ]; then
                echo "-------------------------------------------"
                first_entry=0
            fi
            echo "[思考] $text"
        fi
    fi

    # 回答内容
    if echo "$line" | grep -q '"type":"text"'; then
        text=$(echo "$line" | python3 -c "import json,sys;o=json.load(sys.stdin);print(o.get('text',''))" 2>/dev/null)
        if [ -n "$text" ] && ! echo "$text" | grep -qE '^\{'; then
            if [ $first_entry -eq 1 ]; then
                echo "-------------------------------------------"
                first_entry=0
            fi
            echo "[回答] $text"
            echo "-------------------------------------------"
        fi
    fi

done

echo "=================================="
echo " 显示最近 $LIMIT 组对话"
echo "=================================="

Dockerfile

# 在 Docker 的核心机制中
# RUN、COPY 和 ADD 会真正向硬盘写入数据,并打包成一个新的、占用空间的“只读层”。
# ENV、USER、WORKDIR、ENTRYPOINT 在镜像的配置清单(Metadata)上修改了几行字,体积为0,不会增加额外的物理层。

# ==========================================
# [阶段 1] 提取外部二进制 (Builder 阶段,不计入最终镜像层数)
# ==========================================
FROM oven/bun:1.3.13-slim AS bun-source

# ==========================================
# [阶段 2] 最终运行环境
# ==========================================
FROM node:25.9-bookworm-slim

# ------------------------------------------
# [Metadata] 全局环境变量 (仅修改元数据,0 物理层)
# ------------------------------------------
ENV OPENCODE_VERSION=1.14.31 \
    OMO_VERSION=3.17.12 \
    HOME=/home/node
#    CONDA_DIR=/opt/conda

WORKDIR ${HOME}

# ------------------------------------------
# [Layer 1] 系统级依赖与基础目录准备
# ------------------------------------------
RUN apt-get update && apt-get install -y \
    curl git procps ca-certificates vim \
    && rm -rf /var/lib/apt/lists/* \
    && ln -sf /usr/bin/vim /usr/bin/vi \
    && mkdir -p /www \
    && chown -R node:node /www ${HOME}

# ------------------------------------------
# [Layer 2] 安装 Conda 环境管理器
# ------------------------------------------
# RUN curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh && \
#    bash /tmp/miniconda.sh -b -p $CONDA_DIR && \
#    rm /tmp/miniconda.sh && \
#    chown -R node:node $CONDA_DIR && \
#    $CONDA_DIR/bin/conda clean -afy

# ------------------------------------------
# [Layer 3] 引入 Bun 工具链
# ------------------------------------------
COPY --from=bun-source --chmod=755 /usr/local/bin/bun /usr/local/bin/bunx /usr/local/bin/

# ------------------------------------------
# [Metadata] 切换用户权限
# ------------------------------------------
USER node
ENV PERSIST_PATHS="${HOME}/.config/opencode ${HOME}/.local/share/opencode ${HOME}/.cache/opencode" \
    PATH="${HOME}/.opencode/bin:${HOME}/.bun/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PATH}"

# ------------------------------------------
# [Layer 4] 安装 OpenCode 核心
# ------------------------------------------
RUN BUN_CONFIG_REGISTRY=https://registry.npmmirror.com curl -fsSL https://opencode.ai/install | bash -s -- -v ${OPENCODE_VERSION}

# ------------------------------------------
# [Layer 5] 安装 OMO 扩展与业务依赖
# ------------------------------------------
RUN bunx oh-my-opencode@${OMO_VERSION} install --no-tui --skip-auth --claude=no --gemini=no --copilot=no && npm install zod

# ------------------------------------------
# [Layer 6] 持久化备份与启动脚本生成
# ------------------------------------------
RUN for path in $PERSIST_PATHS; do \
        dest="${HOME}/backup$path"; \
        mkdir -p "$dest"; \
        # 如果路径存在且不为空,则移动内容到备份目录
        if [ -d "$path" ] && [ "$(ls -A "$path" 2>/dev/null)" ]; then \
            cp -rp "$path/." "$dest/"; \
        fi; \
    done && \
    printf '#!/bin/bash\n\
for path in $PERSIST_PATHS; do\n\
    # 如果目标目录不存在,或者为空(不管是镜像自带的空还是挂载了空的 Volume)\n\
    if [ ! -d "$path" ] || [ -z "$(ls -A "$path" 2>/dev/null)" ]; then\n\
        echo "Initializing/Restoring path: $path"\n\
        # mkdir -p "$path"\n\
        # 从备份处拷贝回来,2>/dev/null 忽略备份源为空时的报错\n\
        cp -rp "${HOME}/backup$path/." "$path/" 2>/dev/null || true\n\
    fi\n\
done\n\
exec "$@"\n' > ${HOME}/entrypoint.sh && \
    chmod +x ${HOME}/entrypoint.sh

# ------------------------------------------
# [Metadata] 容器启动指令
# ------------------------------------------
ENTRYPOINT ["/home/node/entrypoint.sh"]
CMD ["bash"]

Dockerfile buid log

/www/opencode $ docker build -t atibmcom/opencode:1.14.31 .
[+] Building 132.5s (14/14) FINISHED                                                        docker:default
 => [internal] load build definition from Dockerfile                                                  0.0s
 => => transferring dockerfile: 4.26kB                                                                0.0s
 => [internal] load metadata for docker.io/library/node:25.9-bookworm-slim                            0.1s
 => [internal] load metadata for docker.io/oven/bun:1.3.13-slim                                       0.1s
 => [internal] load .dockerignore                                                                     0.0s
 => => transferring context: 2B                                                                       0.0s
 => [stage-1 1/8] FROM docker.io/library/node:25.9-bookworm-slim@sha256:e49fd70491eb042270f974167c87  0.0s
 => => resolve docker.io/library/node:25.9-bookworm-slim@sha256:e49fd70491eb042270f974167c874d624528  0.0s
 => CACHED [bun-source 1/1] FROM docker.io/oven/bun:1.3.13-slim@sha256:7e8ed3961db1cdedf17d516dda879  0.0s
 => => resolve docker.io/oven/bun:1.3.13-slim@sha256:7e8ed3961db1cdedf17d516dda87948cfedbd294f53bf16  0.0s
 => CACHED [stage-1 2/8] WORKDIR /home/node                                                           0.0s
 => [stage-1 3/8] RUN apt-get update && apt-get install -y     curl git procps ca-certificates vim   44.1s
 => [stage-1 4/8] RUN curl -fsSL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64  26.4s
 => [stage-1 5/8] COPY --from=bun-source --chmod=755 /usr/local/bin/bun /usr/local/bin/bunx /usr/loc  0.4s
 => [stage-1 6/8] RUN BUN_CONFIG_REGISTRY=https://registry.npmmirror.com curl -fsSL https://opencode  7.3s
 => [stage-1 7/8] RUN bunx oh-my-opencode@3.17.12 install --no-tui --skip-auth --claude=no --gemini  15.2s
 => [stage-1 8/8] RUN for path in /home/node/.config/opencode /home/node/.local/share/opencode /home  1.6s
 => exporting to image                                                                               37.5s
 => => exporting layers                                                                              22.9s
 => => exporting manifest sha256:f1632a2919f82055a9165c51db0c13b4725f4d0b362145bdbd429242f1811532     0.0s
 => => exporting config sha256:dbf74ef9797d1e657754e3402366e6812760b13b21cd30a38d978920b29a36e2       0.0s
 => => exporting attestation manifest sha256:054419888fa3bcfe78fba0018811e0be79b450f81651ab5bb341696  0.0s
 => => exporting manifest list sha256:e32aa90c6722886a70d4d5666f1a04b3ec0605790baccef680e38e99c63f27  0.0s
 => => naming to docker.io/atibmcom/opencode:1.14.31                                                  0.0s
 => => unpacking to docker.io/atibmcom/opencode:1.14.31                                              14.5s

docker-compose.yml

services:
  opencode:
    container_name: "opencode"
    image: atibmcom/opencode:1.14.29
    restart: unless-stopped
    tty: true
    stdin_open: true
    # mkdir -p data/config/opencode data/local/share/opencode data/cache/opencode data/npm data/www data/envs
    volumes:
      - ./data/config/opencode:/home/node/.config/opencode              # 配置、插件、Agent
      - ./data/local/share/opencode:/home/node/.local/share/opencode    # 会话、鉴权、数据
      - ./data/cache/opencode:/home/node/.cache/opencode                # 缓存,最好加上,要不每次创建重新下载一堆
      - ./data/npm:/home/node/.npm                                      # 插件安装缓存,最好也加上,也是一堆下载
      - ./data/www:/www                                                 # 项目目录
      - ./data/envs:/opt/conda/envs                                     # 环境目录
      - /etc/localtime:/etc/localtime:ro                                # 时区时间同步
      - /etc/timezone:/etc/timezone:ro                                  # 时区时间同步
    # user: "1000:1000"   												# 直接指定 UID:GID
    command: ["opencode", "serve", "--print-logs"]
    environment:
      - TZ=Asia/Shanghai
    networks:
      - ghost_net
    # 限制 Nginx 本身的资源,它很高效,64M 足够
    #deploy:
    #  resources:
    #    limits:
    #      memory: 64M
networks:
  ghost_net:
    external: true

docker up 日志


vm-alpine:/www/opencode$ up
[+] Running 1/1
 ✔ Container opencode  Started                                                                                                                1.0s
vm-alpine:/www/opencode$ log 10
opencode  | INFO  2026-04-30T02:22:51 +341ms service=default version=1.14.30 args=["serve","--print-logs"] process_role=main run_id=4012eb13-5cd1-4fc1-9fe3-8ac057706c0a opencode
opencode  | Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.
opencode  | INFO  2026-04-30T02:22:51 +12ms service=file init
opencode  | INFO  2026-04-30T02:22:51 +46ms service=config path=/home/node/.config/opencode/config.json loading
opencode  | INFO  2026-04-30T02:22:51 +2ms service=config path=/home/node/.config/opencode/opencode.json loading
opencode  | INFO  2026-04-30T02:22:51 +7ms service=config path=/home/node/.config/opencode/opencode.jsonc loading
opencode  | INFO  2026-04-30T02:22:51 +40ms service=server opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 server backend selected
opencode  | opencode server listening on http://0.0.0.0:8080
opencode  | INFO  2026-04-30T02:23:00 +8911ms service=server method=GET path=/ opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request
opencode  | INFO  2026-04-30T02:23:00 +0ms service=server status=started method=GET path=/ opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request
opencode  | INFO  2026-04-30T02:23:00 +3ms service=default directory=/home/node creating instance
opencode  | INFO  2026-04-30T02:23:00 +1ms service=project directory=/home/node fromDirectory
opencode  | INFO  2026-04-30T02:23:00 +2ms service=db path=/home/node/.local/share/opencode/opencode.db opening database
opencode  | INFO  2026-04-30T02:23:00 +5ms service=db count=14 mode=bundled applying migrations
opencode  | INFO  2026-04-30T02:23:00 +8ms service=default directory=/home/node bootstrapping
opencode  | INFO  2026-04-30T02:23:00 +37ms service=config path=/home/node/.opencode/opencode.json loading
opencode  | INFO  2026-04-30T02:23:00 +0ms service=config path=/home/node/.opencode/opencode.jsonc loading
opencode  | INFO  2026-04-30T02:23:00 +135ms service=plugin name=_F loading internal plugin
opencode  | INFO  2026-04-30T02:23:00 +0ms service=plugin name=ZF loading internal plugin
opencode  | INFO  2026-04-30T02:23:00 +1ms service=plugin name=Rh loading internal plugin
opencode  | INFO  2026-04-30T02:23:00 +0ms service=plugin name=d5 loading internal plugin
opencode  | INFO  2026-04-30T02:23:00 +0ms service=plugin name=uh loading internal plugin
opencode  | INFO  2026-04-30T02:23:00 +0ms service=plugin name=kh loading internal plugin
opencode  | INFO  2026-04-30T02:23:48 +48271ms service=plugin path=oh-my-openagent@latest loading plugin
opencode  | INFO  2026-04-30T02:24:00 +11816ms service=server method=GET path=/favicon.ico opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request
opencode  | INFO  2026-04-30T02:24:00 +0ms service=server status=started method=GET path=/favicon.ico opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request
opencode  | INFO  2026-04-30T02:24:23 +23164ms service=bus type=* subscribing
opencode  | INFO  2026-04-30T02:24:23 +4ms service=bus type=command.executed subscribing
opencode  | INFO  2026-04-30T02:24:23 +5ms service=lsp all LSPs are disabled
opencode  | INFO  2026-04-30T02:24:23 +1ms service=bus type=session.updated subscribing
opencode  | INFO  2026-04-30T02:24:23 +0ms service=bus type=message.updated subscribing
opencode  | INFO  2026-04-30T02:24:23 +0ms service=bus type=message.part.updated subscribing
opencode  | INFO  2026-04-30T02:24:23 +0ms service=bus type=session.diff subscribing
opencode  | INFO  2026-04-30T02:24:23 +0ms service=bus type=session.deleted subscribing
opencode  | INFO  2026-04-30T02:24:23 +1ms service=format all formatters are disabled
opencode  | INFO  2026-04-30T02:24:23 +0ms service=format init
opencode  | INFO  2026-04-30T02:24:23 +4ms service=file.watcher directory=/home/node init
opencode  | INFO  2026-04-30T02:24:23 +3ms service=file.watcher directory=/home/node platform=linux backend=inotify watcher backend
opencode  | INFO  2026-04-30T02:24:23 +11ms service=server status=completed duration=83472 method=GET path=/ opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request
opencode  | INFO  2026-04-30T02:24:23 +1ms service=server status=completed duration=23194 method=GET path=/favicon.ico opencode.server.backend=hono opencode.server.backend.reason=stable opencode.installation.channel=latest opencode.installation.version=1.14.30 request

opencode.conf

# 临时证书 openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /www/nginx/data/localssl/opencode.key -out /www/nginx/data/localssl/opencode.crt -subj "/C=CN/CN=opencode.kc.com" -addext "subjectAltName = DNS:opencode.kc.com"
# 用户端,将生成的 .crt 文件安装到 Windows 的 “受信任的根证书颁发机构” 中
# 1. HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name opencode.kc.com 192.168.1.90 192.168.1.201;
    return 301 https://$host$request_uri;
}

# 2. HTTPS 核心配置
server {
    listen 443 ssl;
    server_name opencode.kc.com 192.168.1.90 192.168.1.201;

    # 证书文件路径(记得在 docker 中映射这两个文件)
    ssl_certificate     /etc/nginx/opencode.crt;
    ssl_certificate_key /etc/nginx/opencode.key;

    # 推荐的 SSL 基础优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://opencode:8080;

        # 核心:告知后端现在是 https 环境
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 增加上传限制(如果 Agent 需要处理大文件)
        client_max_body_size 100M;
    }
}

bashrc/profile

# alpine是profile,其它系统可能是bashrc
cat >> ~/.profile << 'EOF'

# opencode 快捷命令
opencode() {
  case "$1" in
    start)
      docker-compose restart
      ;;
    stop )
      docker-compose stop
      ;;
    stats )
      if [ "$2" = "7" ]; then
        docker exec -it opencode opencode stats --days 7
      elif [ "$2" = "model" ]; then
        docker exec -it opencode opencode stats --models
      else
        docker exec -it opencode opencode stats
      fi
      ;;
    cat )
      if [ "$2" = "omo" ]; then
        docker exec -it opencode cat /home/node/.config/opencode/oh-my-openagent.json
      else
        docker exec -it opencode cat /home/node/.config/opencode/opencode.json
      fi
      ;;
    vi )
      if [ "$2" = "omo" ]; then
        docker exec -it opencode vi /home/node/.config/opencode/oh-my-openagent.json
      else
        docker exec -it opencode vi /home/node/.config/opencode/opencode.json
      fi
      ;;
    * )
      echo "用法:"
      echo "opencode            # 帮助"
      echo "opencode start      # 重启容器"
      echo "opencode stop       # 停止容器"
      echo "opencode stats      # 统计"
      echo "opencode stats 7    # 7天统计"
      echo "opencode stats model# 模型统计"
      echo "opencode cat        # 查看主配置"
      echo "opencode cat oc     # 查看主配置"
      echo "opencode cat omo    # 查看 oh-my-openagent"
      echo "opencode vi         # 编辑主配置"
      echo "opencode vi oc      # 编辑主配置"
      echo "opencode vi omo     # 编辑 oh-my-openagent"
      ;;
  esac
}
EOF

source ~/.profile