diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index b0afabe..72956aa 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -257,16 +257,6 @@ if [ ! -f "$RUNCC_SCRIPT" ]; then echo " $(status_ok) 已从模板创建 runcc.sh" fi -# 检查并创建 runoc.sh(从模板复制) -RUNOC_SCRIPT="$WORKSPACE/.devcontainer/.volumes/bin/runoc.sh" -RUNOC_TEMPLATE="$SCRIPT_DIR/templates/runoc.sh" -if [ ! -f "$RUNOC_SCRIPT" ]; then - mkdir -p "$(dirname "$RUNOC_SCRIPT")" - cp "$RUNOC_TEMPLATE" "$RUNOC_SCRIPT" - chmod +x "$RUNOC_SCRIPT" - echo " $(status_ok) 已从模板创建 runoc.sh" -fi - # 配置 Open Code echo "配置 Open Code..." if [ -f "$WORKSPACE/.devcontainer/opencode.json.example" ]; then diff --git a/.devcontainer/templates/bashrc.tail.sh b/.devcontainer/templates/bashrc.tail.sh index 07d4511..45be232 100644 --- a/.devcontainer/templates/bashrc.tail.sh +++ b/.devcontainer/templates/bashrc.tail.sh @@ -63,21 +63,6 @@ alias cc5='cc 5' alias cc5t='cc 5t' alias cc51='cc 51' -# OpenCode 启动函数(参数透传至 runoc.sh) -oc() { {{BIN_PATH}}/runoc.sh "$@"; } - -# 模型快捷方式: oc51, oc 51 ... -alias oc45='oc 45' -alias oc45a='oc 45a' -alias oc45f='oc 45f' -alias oc46='oc 46' -alias oc46v='oc 46v' -alias oc46vf='oc 46vf' -alias oc47='oc 47' -alias oc5='oc 5' -alias oc5t='oc 5t' -alias oc51='oc 51' - # tmux pane 级模型继承:从 pane option 读取模型配置(由 runcc.sh 写入) # 覆盖 session 级环境变量,实现同 session 不同 pane 的模型隔离 if [ -n "${TMUX:-}" ]; then @@ -89,11 +74,6 @@ if [ -n "${TMUX:-}" ]; then fi unset _model - _oc_model="$(tmux show-option -pv @opencode_model 2>/dev/null || true)" - if [ -n "$_oc_model" ]; then - export OPENCODE_MODEL="$_oc_model" - fi - unset _oc_model fi # Docker 组提示(仅在需要时显示) diff --git a/.devcontainer/templates/runoc.sh b/.devcontainer/templates/runoc.sh deleted file mode 100755 index 931e9c7..0000000 --- a/.devcontainer/templates/runoc.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash -# OpenCode 启动脚本,支持通过参数选择 GLM 模型版本 -# -# 用法: runoc.sh [模型] -# -# 模型: 45|45a|45f|46|46v|46vf|47|5|5t|51 (默认 51) - -set -euo pipefail - -PROJECT_CONFIG="/workspace/opencode.json" -GLOBAL_CONFIG="$HOME/.config/opencode/opencode.json" - -# 参数解析 -MODEL_KEY="" - -while [ $# -gt 0 ]; do - case "$1" in - -h|--help) - echo "用法: runoc.sh [模型]" - echo "" - echo "模型: 45|45a|45f|46|46v|46vf|47|5|5t|51 (默认 51)" - exit 0 - ;; - *) - MODEL_KEY="$1"; shift - ;; - esac -done - -MODEL_KEY="${MODEL_KEY:-51}" -case "$MODEL_KEY" in - 45) MODEL="zhipuai-coding-plan/glm-4.5" ;; - 45a) MODEL="zhipuai-coding-plan/glm-4.5-air" ;; - 45f) MODEL="zhipuai-coding-plan/glm-4.5-flash" ;; - 46) MODEL="zhipuai-coding-plan/glm-4.6" ;; - 46v) MODEL="zhipuai-coding-plan/glm-4.6v" ;; - 46vf) MODEL="zhipuai-coding-plan/glm-4.6v-flash" ;; - 47) MODEL="zhipuai-coding-plan/glm-4.7" ;; - 5) MODEL="zhipuai-coding-plan/glm-5" ;; - 5t) MODEL="zhipuai-coding-plan/glm-5-turbo" ;; - 51) MODEL="zhipuai-coding-plan/glm-5.1" ;; - *) - echo "未知模型: $MODEL_KEY (可选: 45|45a|45f|46|46v|46vf|47|5|5t|51)" - exit 1 - ;; -esac - -# ── tmux 模型传播(确保子 pane 能获取正确模型)───────── -if [ -n "${TMUX:-}" ]; then - SESSION_ID="$(tmux display-message -p '#{session_id}')" - - # session 级环境变量 - tmux setenv -t "$SESSION_ID" OPENCODE_MODEL "$MODEL" - - # pane 级选项(.bashrc 会在新 shell 启动时读取) - tmux set-option -p @opencode_model "$MODEL" -fi - -# ── OpenCode 自更新检查(每日一次)── -LAST_UPDATE_FILE="$HOME/.cache/opencode_update_last_run" -TODAY=$(date +%Y-%m-%d) -mkdir -p "$(dirname "$LAST_UPDATE_FILE")" - -if [ ! -f "$LAST_UPDATE_FILE" ] || [ "$(cat "$LAST_UPDATE_FILE" 2>/dev/null)" != "$TODAY" ]; then - opencode upgrade 2>/dev/null || true - echo "$TODAY" > "$LAST_UPDATE_FILE" -fi - -# ── 构建启动参数 ── -OC_ARGS=(-m "$MODEL") - -echo "启动 OpenCode (模型: $MODEL)" -opencode "${OC_ARGS[@]}" diff --git a/README.md b/README.md index 1a598db..e29ab2f 100644 --- a/README.md +++ b/README.md @@ -44,22 +44,122 @@ specs/ # speckit 功能规格 ## 快速开始 -### 1. 环境准备 +### 1. 环境准备(必须) + +所有开发方式(VS Code Dev Containers、docker-compose、本地)共享同一套前置步骤: ```bash # 克隆项目 +git clone <仓库地址> workspace && cd workspace/.devcontainer + +# ① 创建环境配置(首次必须) +cp .env.example .env + +# ② 编辑 .env,至少修改以下配置: +# - GIT_USER_NAME / GIT_USER_EMAIL — Git 用户信息 +# - API_KEY — 智谱 GLM API 密钥(可选,留空则跳过认证配置) +# - DOCKER_GID — 宿主机 docker 组 GID(getent group docker | cut -d: -f3) +# - CONTAINER_USER_UID / GID — 与宿主机用户一致(id -u / id -g) + +# ③ 预下载构建资源(首次必须,后续按需增量更新) +bash download-resources.sh +``` + +#### download-resources.sh 资源预下载 + +[`download-resources.sh`](.devcontainer/download-resources.sh) 预下载所有网络资源到 `.devcontainer/.cache/`,Dockerfile 构建时通过 `--mount=type=bind` 直接使用本地缓存,**无需构建时访问外网**。支持增量更新和校验。 + +```bash +bash download-resources.sh # 下载全部资源(首次必须) +bash download-resources.sh --skip-extensions # 跳过 VSCode 扩展(节省时间) +bash download-resources.sh --force-update # 强制更新所有包 +bash download-resources.sh --cleanup-only # 仅清理旧版本包 +``` + +预下载的资源包括: + +| 资源 | 用途 | +|------|------| +| uv + Python 3.12 | Python 包管理器和运行时 | +| nvm + Node.js 22 | 前端运行时和包管理 | +| npm 全局包 | Claude Code、Playwright MCP、TypeScript 等 | +| Google Chrome | Playwright headed 模式和 chrome-devtools-mcp | +| jj (Jujutsu) | 版本控制工具 | +| VSCode 扩展 (.vsix) | 20+ 开发扩展离线包 | +| spec-kit | speckit 规格工具 | +| Claude 插件市场 | claude-plugins-official、Svelte、superpowers 等 | + +所有资源版本在 `.env` 中配置(`UV_VERSION`、`NODE_VERSION`、`CHROME_VERSION` 等),更新版本后重新运行脚本即可。 + +#### .env 配置参考 + +完整配置见 [`.devcontainer/.env.example`](.devcontainer/.env.example),常用项: + +| 配置项 | 默认值 | 说明 | +|--------|--------|------| +| `GIT_USER_NAME` | `arno` | Git 用户名 | +| `GIT_USER_EMAIL` | — | Git 邮箱 | +| `API_KEY` | 空 | 智谱 GLM API 密钥 | +| `DOCKER_ENABLED` | `false` | 是否启用容器内 Docker | +| `DOCKER_GID` | `984` | 宿主机 docker 组 GID | +| `CONTAINER_USER_UID` | `1000` | 容器用户 UID | +| `CONTAINER_USER_GID` | `1000` | 容器用户 GID | +| `DISPLAY_ON_HOST` | `false` | GUI 输出到宿主机(仅 Linux) | +| `CONTAINER_CPUS` | `6` | CPU 核心数限制 | +| `CONTAINER_MEMORY` | `16G` | 内存限制 | + +### 2. 启动开发环境 + +资源下载完成后,选择以下任一方式启动: + +#### 方式 A: VS Code Dev Containers(推荐) + +1. 安装 VS Code 扩展 `ms-vscode-remote.remote-containers` +2. 在 VS Code 中打开项目根目录 +3. `Ctrl+Shift+P` → `Dev Containers: Open Folder in Container...` +4. VS Code 自动读取 [`.devcontainer/devcontainer.json`](.devcontainer/devcontainer.json) 构建、启动容器并安装扩展 + +`devcontainer.json` 核心配置: + +| 配置 | 说明 | +|------|------| +| `dockerComposeFile` | 组合 `docker-compose.yml` + `docker-compose.display.yml`(X11 转发) | +| `service: app` | 使用 `app` 服务 | +| `postCreateCommand` | 容器创建后自动执行 `.devcontainer/post-create.sh`(配置 Git、jj、Claude Code、MCP、插件等) | +| `customizations.vscode.extensions` | 预装 Claude Code、Ruff、Playwright、Mermaid 等 20+ 扩展 | + +#### 方式 B: docker-compose 命令行 + +```bash +cd .devcontainer +docker compose up -d +docker exec -it team bash +``` + +#### 方式 C: 本地开发(不使用容器) + +不使用容器时,需手动安装工具链(uv、nvm、jj 等): + +```bash jj clone <仓库地址> workspace && cd workspace - -# Python 环境(需 uv) uv python install 3.12 - -# 前端环境(需 nvm) nvm install --lts ``` -详细环境搭建见 [`docs/管理-开发环境搭建.md`](docs/管理-开发环境搭建.md)。 +详细步骤见 [`docs/管理-开发环境搭建.md`](docs/管理-开发环境搭建.md)。 -### 2. 启动 Agent 团队 +#### 数据持久化 + +`.devcontainer/.volumes/` 目录映射以下数据,容器重建不丢失: + +| 目录 | 用途 | +|------|------| +| `.volumes/ssh/` | SSH 密钥和配置 | +| `.volumes/claude/` | Claude Code 配置(settings.json) | +| `.volumes/jj/` | jj 版本控制配置 | +| `.volumes/bin/` | 运行时脚本(runcc.sh) | + +### 3. 启动 Agent 团队 ```bash # 在 tmux 中启动 5 面板团队工作空间 @@ -86,7 +186,7 @@ nvm install --lts /isos-test # 测试工程师 ``` -### 3. 常用命令 +### 4. 常用命令 ```bash # 提交并推送(jj 工作流) @@ -105,7 +205,7 @@ nvm install --lts /isos-md-export # Markdown 导出 docx/pdf ``` -### 4. 开发验证 +### 5. 开发验证 ```bash # 服务端 (cd apps/server) diff --git a/member/vscode.chat.md b/member/vscode.chat.md index 79b7818..da13f4a 100644 --- a/member/vscode.chat.md +++ b/member/vscode.chat.md @@ -1 +1,2 @@ -# vscode 的对话记录 \ No newline at end of file +# vscode 的对话记录 +