initial: team agent workstation for 6-repo matrix
- Dockerfile (Node/Python/Go/Bun + claude-code + gh cli)
- docker-compose.yml (flexible REPOS_DIR, 7 mounts, 6 cache volumes)
- CLAUDE.md (team conventions + red lines + per-repo build/test cmds)
- .claude/settings.json (allow/deny permissions)
- Makefile + scripts/{enter,bootstrap,run-task}.sh
- README.md (onboarding guide)
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(git status*)",
|
||||||
|
"Bash(git diff*)",
|
||||||
|
"Bash(git log*)",
|
||||||
|
"Bash(git branch*)",
|
||||||
|
"Bash(git checkout*)",
|
||||||
|
"Bash(git switch*)",
|
||||||
|
"Bash(git add*)",
|
||||||
|
"Bash(git commit*)",
|
||||||
|
"Bash(git pull*)",
|
||||||
|
"Bash(git fetch*)",
|
||||||
|
"Bash(git stash*)",
|
||||||
|
"Bash(git push origin*)",
|
||||||
|
"Bash(gh pr*)",
|
||||||
|
"Bash(gh issue*)",
|
||||||
|
"Bash(gh run*)",
|
||||||
|
"Bash(gh workflow*)",
|
||||||
|
"Bash(gh auth status*)",
|
||||||
|
"Bash(npm install*)",
|
||||||
|
"Bash(npm test*)",
|
||||||
|
"Bash(npm run*)",
|
||||||
|
"Bash(npm audit*)",
|
||||||
|
"Bash(npm outdated*)",
|
||||||
|
"Bash(pnpm install*)",
|
||||||
|
"Bash(pnpm run*)",
|
||||||
|
"Bash(pnpm test*)",
|
||||||
|
"Bash(bun install*)",
|
||||||
|
"Bash(bun test*)",
|
||||||
|
"Bash(bun run*)",
|
||||||
|
"Bash(pip install*)",
|
||||||
|
"Bash(pip list*)",
|
||||||
|
"Bash(uv pip*)",
|
||||||
|
"Bash(uv run*)",
|
||||||
|
"Bash(pytest*)",
|
||||||
|
"Bash(ruff*)",
|
||||||
|
"Bash(black*)",
|
||||||
|
"Bash(mypy*)",
|
||||||
|
"Bash(alembic*)",
|
||||||
|
"Bash(go build*)",
|
||||||
|
"Bash(go test*)",
|
||||||
|
"Bash(go vet*)",
|
||||||
|
"Bash(go fmt*)",
|
||||||
|
"Bash(go mod*)",
|
||||||
|
"Bash(go list*)",
|
||||||
|
"Bash(make*)",
|
||||||
|
"Bash(prisma*)",
|
||||||
|
"Bash(npx prisma*)",
|
||||||
|
"Bash(docker compose build*)",
|
||||||
|
"Bash(docker compose config*)",
|
||||||
|
"Bash(docker compose ps*)",
|
||||||
|
"Bash(docker compose logs*)",
|
||||||
|
"Bash(rg*)",
|
||||||
|
"Bash(fd*)",
|
||||||
|
"Bash(jq*)",
|
||||||
|
"Bash(ls*)",
|
||||||
|
"Bash(cat*)",
|
||||||
|
"Bash(head*)",
|
||||||
|
"Bash(tail*)",
|
||||||
|
"Bash(wc*)"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"Bash(git push --force*)",
|
||||||
|
"Bash(git push -f*)",
|
||||||
|
"Bash(git push origin main*)",
|
||||||
|
"Bash(git push origin master*)",
|
||||||
|
"Bash(git reset --hard*)",
|
||||||
|
"Bash(git clean -fd*)",
|
||||||
|
"Bash(git commit --amend*)",
|
||||||
|
"Bash(rm -rf /*)",
|
||||||
|
"Bash(rm -rf ~*)",
|
||||||
|
"Bash(sudo*)",
|
||||||
|
"Bash(docker system prune*)",
|
||||||
|
"Bash(docker volume rm*)",
|
||||||
|
"Bash(terraform destroy*)",
|
||||||
|
"Bash(terraform apply*)",
|
||||||
|
"Bash(kubectl delete*)",
|
||||||
|
"Bash(kubectl apply*)",
|
||||||
|
"Bash(az containerapp update*)",
|
||||||
|
"Bash(az containerapp delete*)",
|
||||||
|
"Bash(alembic downgrade*)",
|
||||||
|
"Bash(dropdb*)",
|
||||||
|
"Bash(psql*production*)",
|
||||||
|
"Read(./**/.env)",
|
||||||
|
"Read(./**/.env.*)",
|
||||||
|
"Read(./**/secrets/**)",
|
||||||
|
"Read(./**/*.pem)",
|
||||||
|
"Read(./**/*.key)",
|
||||||
|
"Read(./casdoor-internal/conf/app.conf)",
|
||||||
|
"Write(./**/.env)",
|
||||||
|
"Write(./**/.env.*)",
|
||||||
|
"Write(./**/secrets/**)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"DISABLE_TELEMETRY": "0",
|
||||||
|
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "32000"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# =================================================================
|
||||||
|
# 登录方式(订阅模式无需填任何 KEY)
|
||||||
|
# =================================================================
|
||||||
|
#
|
||||||
|
# 方式 A(推荐):Claude Max/Pro 订阅 OAuth
|
||||||
|
# —— 本文件任何 KEY 都不用填。启动容器后运行 `/login` 即可。
|
||||||
|
# 凭证会写入 docker named volume `claude-home`,下次启动自动复用。
|
||||||
|
#
|
||||||
|
# 方式 B:Anthropic API Key(按量计费,适合 CI 无人值守)
|
||||||
|
# ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# 仓库根目录(如果你的 6 个仓库不在 ai-ops 的父目录)
|
||||||
|
# =================================================================
|
||||||
|
# 默认:REPOS_DIR 不设 → 使用 ai-ops/../ (即 ai-ops 的同级)
|
||||||
|
# 自定义示例:
|
||||||
|
# REPOS_DIR=/Users/alice/dev/work
|
||||||
|
# REPOS_DIR=${HOME}/projects
|
||||||
|
# 注意:6 个仓库必须都在 REPOS_DIR 下,名字与 GitHub 一致:
|
||||||
|
# chat-gw / xiaoshou / gongdan / casdoor-internal / CloudCostbrank / lobechat-enterprise
|
||||||
|
# REPOS_DIR=${HOME}/work
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Git / GitHub(Agent 提 PR 时需要)
|
||||||
|
# =================================================================
|
||||||
|
# GH_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
|
GIT_AUTHOR_NAME=Your Name
|
||||||
|
GIT_AUTHOR_EMAIL=you@example.com
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# 企业合规:走 AWS Bedrock(代替 Anthropic API)
|
||||||
|
# =================================================================
|
||||||
|
# CLAUDE_CODE_USE_BEDROCK=1
|
||||||
|
# AWS_REGION=us-west-2
|
||||||
|
# AWS_PROFILE=default
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# 模型覆盖(默认 Opus 4.7,1M 上下文)
|
||||||
|
# =================================================================
|
||||||
|
# ANTHROPIC_MODEL=claude-sonnet-4-6
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.claude/state/
|
||||||
|
.claude/logs/
|
||||||
|
.claude/sessions/
|
||||||
|
.claude/projects/
|
||||||
|
.claude/todos/
|
||||||
|
.omc/
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# 6-Repo Enterprise Matrix — Agent Operating Guide
|
||||||
|
|
||||||
|
你是这个企业级 SaaS 矩阵的维护者。工作目录 `/workspace` 挂载了 6 个协同工作的仓库。
|
||||||
|
|
||||||
|
## 仓库清单与职责
|
||||||
|
|
||||||
|
| 目录 | 角色 | 栈 | 端口 | 测试/构建 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `chat-gw/` | MCP 工具网关(权限 + 审计 + 路由) | Python 3.12 / FastAPI / asyncpg / Redis | 8000 | `pytest`;`docker compose up --build -d` |
|
||||||
|
| `xiaoshou/` | B2B 销售管理(客户 / 订单 / 账单) | FastAPI + React 18 / AntD 5 / Vite 5 | 后端 8000 / 前端 5173 | `pytest` + `npm run build`;`alembic upgrade head` |
|
||||||
|
| `gongdan/` | 工单系统 + KB 聊天 | NestJS + React + Python FastAPI | 后端 3000 / KB 8001 / 前端 5173 | `npm test`;`prisma migrate dev`;`pytest kb-chat-python` |
|
||||||
|
| `casdoor-internal/` | IAM(Casdoor fork) | Go 1.25 / Beego / xorm / PostgreSQL | 8000 | `make ut`;`make fmt vet`;`make run` |
|
||||||
|
| `CloudCostbrank/` | 多云成本聚合 | Python FastAPI + Celery + SQLAlchemy 2.0 | 8000 | `pytest`;`alembic upgrade head`;`docker compose up` |
|
||||||
|
| `lobechat-enterprise/` | 企业版聊天前端 | Next.js 16 + pgvector + Drizzle | 3010 | `bun test`;`docker compose build`;pnpm monorepo |
|
||||||
|
|
||||||
|
## 系统拓扑
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──── 用户浏览器 ────┐
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
[lobechat-enterprise] [xiaoshou / gongdan 前端]
|
||||||
|
│ │
|
||||||
|
│ ◄── JWT via Casdoor ──►
|
||||||
|
▼ ▼
|
||||||
|
[chat-gw MCP] ◄──► [xiaoshou API] [gongdan API] [CloudCostbrank API]
|
||||||
|
│ ▲
|
||||||
|
└── 统一身份 ────► [casdoor-internal]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 工作原则
|
||||||
|
|
||||||
|
1. **改动前先读当前仓库的 README / Makefile / package.json**,遵循本仓库既有的命名、lint、测试约定;各仓库风格不统一,不要跨仓库硬套。
|
||||||
|
2. **跨仓库改动要成套提 PR**:例如改 Casdoor 的 role claim 字段,必须同步更新 chat-gw、xiaoshou、gongdan、lobechat 的 JWT 解析代码,并在 PR 描述里互相链接。
|
||||||
|
3. **验证闭环前不得声称完成**:改了 Python → `pytest`;改了 Go → `make ut`;改了前端 → `npm run build`;改了 SQL 模型 → 跑 `alembic revision --autogenerate` 确认 diff。
|
||||||
|
4. **提 PR 而非直推 main**:使用 `gh pr create`,描述必须含 "What / Why / Test"。
|
||||||
|
5. **数据库迁移**:xiaoshou 当前有"pending migrations"遗留问题,任何 model 改动都要显式 `alembic revision` 并检查生成的文件。
|
||||||
|
|
||||||
|
## 硬红线(禁止)
|
||||||
|
|
||||||
|
- ❌ 修改 `.env` / `secrets/**` / `conf/app.conf`(casdoor-internal 已 `skip-worktree`)
|
||||||
|
- ❌ 直接 push 到 main / master,force push 任何分支
|
||||||
|
- ❌ 跑 `docker system prune`、`rm -rf /`、`terraform destroy`、`kubectl delete`
|
||||||
|
- ❌ 读取或打印任何包含 `TOKEN` / `SECRET` / `PASSWORD` / `AZURE_STORAGE_CONNECTION_STRING` 的值
|
||||||
|
- ❌ 触碰 lobechat-enterprise 的 242 个 i18n 文件里的 "Enterprise AI Workspace" 品牌字符串(这是 de-brand 改动,升级上游时必须保留)
|
||||||
|
- ❌ 对 casdoor-internal 的 upstream merge 留下未标注的冲突决策
|
||||||
|
|
||||||
|
## CI/CD 现状(每个仓库自带 workflow)
|
||||||
|
|
||||||
|
- `chat-gw/.github/workflows/main_gaw-chat-tools.yml` — Azure 部署
|
||||||
|
- `xiaoshou/.github/workflows/{ci,deploy,frontend-deploy}.yml` — CI + 前后端部署
|
||||||
|
- `gongdan/.github/workflows/{backend-deploy,post-deploy-smoke,azure-static-web-apps-*}.yml`
|
||||||
|
- `casdoor-internal/.github/workflows/{build,build-and-deploy,sync}.yml` — 含上游同步
|
||||||
|
- `CloudCostbrank/` — **缺 CI,需补齐(优先级 P1)**
|
||||||
|
- `lobechat-enterprise/.github/workflows/deploy-aca.yml` — 仅部署,**缺 CI(优先级 P1)**
|
||||||
|
|
||||||
|
任何会改变 lint / test 行为的 PR,都要先本地跑一遍对应 workflow 的核心命令。
|
||||||
|
|
||||||
|
## 常用任务入口
|
||||||
|
|
||||||
|
- 跨仓库搜索:`rg -t py '<pattern>' chat-gw xiaoshou CloudCostbrank`
|
||||||
|
- 依赖审计:`cd <repo> && npm audit` / `pip list --outdated` / `go list -u -m all`
|
||||||
|
- 启动真实环境验证:`cd <repo> && docker compose up -d`,完事 `docker compose down -v`
|
||||||
|
- 提交前自我审查:调用 `code-reviewer` 子 agent,不要自评自批
|
||||||
|
|
||||||
|
## 失败处理
|
||||||
|
|
||||||
|
- CI 红:读 `gh run view <id> --log-failed`,定位到文件再动手,不要猜
|
||||||
|
- Casdoor upstream merge 冲突:先 `git log --oneline origin/upstream-main ^HEAD` 看上游新增,按 `sync.yml` 的策略逐个 hunk 决策
|
||||||
|
- 测试 flake:不要直接 `@pytest.mark.skip`,先 rerun 3 次确认是否真 flake
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
FROM node:22-bookworm
|
||||||
|
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG GO_VERSION=1.25.0
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive \
|
||||||
|
PATH=/usr/local/go/bin:/root/go/bin:/root/.bun/bin:/root/.local/bin:$PATH \
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
|
PIP_NO_CACHE_DIR=off \
|
||||||
|
PIP_DISABLE_PIP_VERSION_CHECK=on
|
||||||
|
|
||||||
|
# 换成清华 Debian 镜像(国内网络更稳)+ apt 重试策略
|
||||||
|
RUN sed -i 's|http://deb.debian.org|https://mirrors.tuna.tsinghua.edu.cn|g; s|http://security.debian.org|https://mirrors.tuna.tsinghua.edu.cn/debian-security|g' /etc/apt/sources.list.d/debian.sources \
|
||||||
|
&& echo 'Acquire::Retries "8";' > /etc/apt/apt.conf.d/80-retries \
|
||||||
|
&& echo 'Acquire::http::Timeout "60";' >> /etc/apt/apt.conf.d/80-retries \
|
||||||
|
&& echo 'Acquire::https::Timeout "60";' >> /etc/apt/apt.conf.d/80-retries
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends --fix-missing \
|
||||||
|
git curl ca-certificates gnupg lsb-release \
|
||||||
|
make build-essential \
|
||||||
|
python3 python3-pip python3-venv python3-dev \
|
||||||
|
postgresql-client redis-tools \
|
||||||
|
jq ripgrep fd-find less vim-tiny tini \
|
||||||
|
&& ln -s /usr/bin/fdfind /usr/local/bin/fd \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${TARGETARCH}.tar.gz" \
|
||||||
|
| tar -C /usr/local -xz
|
||||||
|
|
||||||
|
RUN curl -fsSL https://bun.sh/install | bash
|
||||||
|
|
||||||
|
RUN npm install -g pnpm@latest @anthropic-ai/claude-code
|
||||||
|
|
||||||
|
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
||||||
|
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||||
|
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
|
||||||
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
|
||||||
|
> /etc/apt/sources.list.d/github-cli.list \
|
||||||
|
&& apt-get update && apt-get install -y --no-install-recommends gh \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN pip install --break-system-packages --no-cache-dir \
|
||||||
|
uv ruff black pytest pytest-asyncio httpx
|
||||||
|
|
||||||
|
RUN git config --system --add safe.directory '*' \
|
||||||
|
&& git config --system pull.rebase false \
|
||||||
|
&& git config --system init.defaultBranch main
|
||||||
|
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||||
|
CMD ["claude"]
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
.PHONY: help bootstrap build up enter task clean logout
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Targets:"
|
||||||
|
@echo " bootstrap 一键初始化:clone 6 仓库 + 构建镜像"
|
||||||
|
@echo " build (重)构建镜像"
|
||||||
|
@echo " enter 进入容器(交互式)"
|
||||||
|
@echo " task CMD=.. 非交互执行单任务,例: make task CMD='审计 6 仓库的过时依赖'"
|
||||||
|
@echo " logout 清掉容器内的登录状态"
|
||||||
|
@echo " clean 删除镜像和所有卷(慎用)"
|
||||||
|
|
||||||
|
bootstrap:
|
||||||
|
./scripts/bootstrap.sh
|
||||||
|
|
||||||
|
build:
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
up enter:
|
||||||
|
./scripts/enter.sh
|
||||||
|
|
||||||
|
task:
|
||||||
|
@[ -n "$(CMD)" ] || (echo "用法: make task CMD='<任务描述>'" && exit 1)
|
||||||
|
./scripts/run-task.sh "$(CMD)"
|
||||||
|
|
||||||
|
logout:
|
||||||
|
docker volume rm ai-ops_claude-home 2>/dev/null || true
|
||||||
|
@echo "已清除登录状态,下次 enter 需要重新 /login"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
docker compose down -v --rmi local
|
||||||
|
@echo "镜像和卷已清除"
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
# ai-ops —— 六仓库企业矩阵的 Agent 工作站
|
||||||
|
|
||||||
|
给 `chat-gw / xiaoshou / gongdan / casdoor-internal / CloudCostbrank / lobechat-enterprise`
|
||||||
|
这六个仓库提供一个开箱即用的 Claude Code 容器化工作环境。
|
||||||
|
|
||||||
|
每个团队成员**在自己的机器上**跑自己的容器,用自己的 Claude Max/Pro 订阅登录。
|
||||||
|
共享的只是这份仓库里的 Dockerfile / CLAUDE.md / settings.json。
|
||||||
|
|
||||||
|
## 前置条件
|
||||||
|
|
||||||
|
- **macOS / Linux**,装好 Docker Desktop(>= 4.30)并能拉公网镜像
|
||||||
|
- 有 **Claude Max 或 Pro 订阅**(或 Anthropic API Key)
|
||||||
|
- 能访问 6 个业务仓库的 GitHub 权限(已配好 ssh-key 或 gh auth login)
|
||||||
|
|
||||||
|
## 快速上手(3 分钟)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. clone 本仓库(ai-ops)到你想放的地方,例如 ~/work
|
||||||
|
cd ~/work
|
||||||
|
git clone git@github.com:your-org/ai-ops.git
|
||||||
|
cd ai-ops
|
||||||
|
|
||||||
|
# 2. 一键初始化:clone 6 个业务仓库 + 构建镜像
|
||||||
|
make bootstrap
|
||||||
|
|
||||||
|
# 3. 进容器并登录
|
||||||
|
make enter
|
||||||
|
# 容器内:
|
||||||
|
/login # 浏览器完成 Claude Max/Pro 授权
|
||||||
|
/status # 确认登录成功
|
||||||
|
```
|
||||||
|
|
||||||
|
完成后,容器里 `/workspace` 下能看到 7 个目录(6 个业务仓库 + `ai-ops` 本身)。
|
||||||
|
|
||||||
|
## 目录约定
|
||||||
|
|
||||||
|
默认布局(`REPOS_DIR` 不设时):
|
||||||
|
|
||||||
|
```
|
||||||
|
~/work/ ← 任意名字
|
||||||
|
├── ai-ops/ ← 本仓库
|
||||||
|
├── chat-gw/
|
||||||
|
├── xiaoshou/
|
||||||
|
├── gongdan/
|
||||||
|
├── casdoor-internal/
|
||||||
|
├── CloudCostbrank/
|
||||||
|
└── lobechat-enterprise/
|
||||||
|
```
|
||||||
|
|
||||||
|
如果你 6 个仓库放在别处,编辑 `.env`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
REPOS_DIR=/Users/alice/projects
|
||||||
|
```
|
||||||
|
|
||||||
|
然后 `make build && make enter` 即可。
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make enter # 交互进入 Agent
|
||||||
|
make task CMD="扫描 6 仓库的 CVE 并提 PR" # 非交互单任务
|
||||||
|
make logout # 清除登录状态
|
||||||
|
make build # 重新构建镜像(改了 Dockerfile 后)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 权限模型
|
||||||
|
|
||||||
|
- 容器内的 Agent 按 `.claude/settings.json` 的 allow/deny 列表行事:
|
||||||
|
- ✅ 允许:git 操作、`pytest` / `npm test` / `make` / `gh pr`
|
||||||
|
- ❌ 拒绝:`git push --force`、`rm -rf /`、读 `.env`、`alembic downgrade`、生产数据库操作
|
||||||
|
- 你宿主机的 `~/.ssh` 和 `~/.gitconfig` 只读挂载到容器内,git push 能用,但 Agent 改不了你本机配置
|
||||||
|
- 登录凭证存在 docker volume `claude-home`,**不要把这个 volume 导出给队友**——每人各自 `/login` 自己的订阅
|
||||||
|
|
||||||
|
## 改团队规范(CLAUDE.md / settings.json)
|
||||||
|
|
||||||
|
这两个文件是**全队共享的 Agent 行为约束**:
|
||||||
|
|
||||||
|
- `CLAUDE.md` —— 告诉 Agent 每个仓库是做什么的、该怎么测、红线在哪
|
||||||
|
- `.claude/settings.json` —— allow/deny 权限清单
|
||||||
|
|
||||||
|
改动流程:**提 PR 到本仓库(ai-ops),团队 review 合并**。每人下次 `make build && make enter` 就同步到本地。
|
||||||
|
|
||||||
|
## 出问题排查
|
||||||
|
|
||||||
|
**Docker pull 失败 / TLS 证书错误**
|
||||||
|
—— 检查是否有 VPN / 代理在做 HTTPS 拦截(例如 Astrill 的 OpenWeb 模式)。换成 WireGuard / StealthVPN,或关闭 VPN 后再拉镜像。
|
||||||
|
|
||||||
|
**apt 装包失败**
|
||||||
|
—— Dockerfile 已配清华镜像 + 重试 8 次。如果仍失败,检查网络对 `mirrors.tuna.tsinghua.edu.cn` 的访问。
|
||||||
|
|
||||||
|
**`/login` 后仍提示未登录**
|
||||||
|
—— 确认你的 Claude 订阅类型是 Max 或 Pro。Free 账号没有 Claude Code 权限。
|
||||||
|
|
||||||
|
**想切到 API Key 模式**
|
||||||
|
—— 编辑 `.env`,填 `ANTHROPIC_API_KEY=sk-ant-...`。API Key 优先级高于订阅。
|
||||||
|
|
||||||
|
## 不做什么
|
||||||
|
|
||||||
|
- **不是**一个跑在云上的服务,不支持 SSH 远程访问
|
||||||
|
- **不是**给 CI/CD 用的(CI 场景另用 `.github/workflows/claude-review.yml` + API Key)
|
||||||
|
- **不**共享登录凭证 —— 每人用自己的订阅,违反 Claude TOS 会被踢
|
||||||
|
|
||||||
|
## 许可 / 归属
|
||||||
|
|
||||||
|
内部工具,仅限团队使用。六个业务仓库的许可证以各自仓库为准。
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
name: ai-ops
|
||||||
|
|
||||||
|
services:
|
||||||
|
claude-agent:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: claude-agent-6repos:latest
|
||||||
|
container_name: claude-agent
|
||||||
|
hostname: claude-agent
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
working_dir: /workspace
|
||||||
|
environment:
|
||||||
|
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
|
||||||
|
ANTHROPIC_MODEL: ${ANTHROPIC_MODEL:-claude-opus-4-7}
|
||||||
|
CLAUDE_CODE_USE_BEDROCK: ${CLAUDE_CODE_USE_BEDROCK:-}
|
||||||
|
AWS_REGION: ${AWS_REGION:-}
|
||||||
|
AWS_PROFILE: ${AWS_PROFILE:-}
|
||||||
|
GH_TOKEN: ${GH_TOKEN:-}
|
||||||
|
GITHUB_TOKEN: ${GH_TOKEN:-}
|
||||||
|
GIT_AUTHOR_NAME: ${GIT_AUTHOR_NAME:-Claude Agent}
|
||||||
|
GIT_AUTHOR_EMAIL: ${GIT_AUTHOR_EMAIL:-claude-agent@local}
|
||||||
|
GIT_COMMITTER_NAME: ${GIT_AUTHOR_NAME:-Claude Agent}
|
||||||
|
GIT_COMMITTER_EMAIL: ${GIT_AUTHOR_EMAIL:-claude-agent@local}
|
||||||
|
TERM: xterm-256color
|
||||||
|
volumes:
|
||||||
|
# REPOS_DIR 默认指向 ai-ops 的父目录;队友可在 .env 里改成自己的工作目录
|
||||||
|
- ${REPOS_DIR:-..}/chat-gw:/workspace/chat-gw
|
||||||
|
- ${REPOS_DIR:-..}/xiaoshou:/workspace/xiaoshou
|
||||||
|
- ${REPOS_DIR:-..}/gongdan:/workspace/gongdan
|
||||||
|
- ${REPOS_DIR:-..}/casdoor-internal:/workspace/casdoor-internal
|
||||||
|
- ${REPOS_DIR:-..}/CloudCostbrank:/workspace/CloudCostbrank
|
||||||
|
- ${REPOS_DIR:-..}/lobechat-enterprise:/workspace/lobechat-enterprise
|
||||||
|
- ./CLAUDE.md:/workspace/CLAUDE.md:ro
|
||||||
|
- ./.claude:/workspace/.claude
|
||||||
|
- claude-home:/root/.claude
|
||||||
|
- pip-cache:/root/.cache/pip
|
||||||
|
- go-cache:/root/go/pkg
|
||||||
|
- npm-cache:/root/.npm
|
||||||
|
- pnpm-store:/root/.local/share/pnpm/store
|
||||||
|
- bun-cache:/root/.bun/install/cache
|
||||||
|
- ${HOME}/.ssh:/root/.ssh:ro
|
||||||
|
# 注意:不要挂载 ~/.gitconfig —— 若宿主机没这个文件,Docker 会
|
||||||
|
# 把它自动创建为「空目录」,导致 git 报错。用上面 GIT_AUTHOR_*
|
||||||
|
# 环境变量就足够了。
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "claude", "--version"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
claude-home:
|
||||||
|
pip-cache:
|
||||||
|
go-cache:
|
||||||
|
npm-cache:
|
||||||
|
pnpm-store:
|
||||||
|
bun-cache:
|
||||||
Executable
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 新成员一键初始化:
|
||||||
|
# 1. 克隆 6 个业务仓库到 REPOS_DIR(默认为 ai-ops 的父目录)
|
||||||
|
# 2. 创建 .env(如果还没有)
|
||||||
|
# 3. 构建 Docker 镜像
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
AI_OPS_DIR="$(pwd)"
|
||||||
|
|
||||||
|
# 读取 .env 里的 REPOS_DIR(如果存在)
|
||||||
|
if [[ -f .env ]]; then
|
||||||
|
# shellcheck disable=SC1091
|
||||||
|
source <(grep -E '^REPOS_DIR=' .env || true)
|
||||||
|
fi
|
||||||
|
REPOS_DIR="${REPOS_DIR:-$(cd .. && pwd)}"
|
||||||
|
|
||||||
|
echo ">>> 仓库将克隆到: $REPOS_DIR"
|
||||||
|
mkdir -p "$REPOS_DIR"
|
||||||
|
|
||||||
|
declare -A REPOS=(
|
||||||
|
[chat-gw]="https://github.com/Fasthei/chat-gw.git"
|
||||||
|
[xiaoshou]="https://github.com/Fasthei/xiaoshou.git"
|
||||||
|
[gongdan]="https://github.com/Fasthei/gongdan.git"
|
||||||
|
[casdoor-internal]="https://github.com/zsbgnw12/casdoor-internal.git"
|
||||||
|
[CloudCostbrank]="https://github.com/zsbgnw12/CloudCostbrank.git"
|
||||||
|
[lobechat-enterprise]="https://github.com/zsbgnw12/lobechat-enterprise.git"
|
||||||
|
)
|
||||||
|
|
||||||
|
for name in "${!REPOS[@]}"; do
|
||||||
|
target="$REPOS_DIR/$name"
|
||||||
|
if [[ -d "$target/.git" ]]; then
|
||||||
|
echo " [skip] $name 已存在"
|
||||||
|
else
|
||||||
|
echo " [clone] $name"
|
||||||
|
git clone "${REPOS[$name]}" "$target"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cd "$AI_OPS_DIR"
|
||||||
|
if [[ ! -f .env ]]; then
|
||||||
|
cp .env.example .env
|
||||||
|
echo ">>> 已创建 .env(订阅模式无需改动;用 API Key 的话填上 ANTHROPIC_API_KEY)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ">>> 构建镜像(首次约 5 分钟)"
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo ">>> 完成。下一步:"
|
||||||
|
echo " ./scripts/enter.sh # 进入容器"
|
||||||
|
echo " 容器内运行 /login # 用你自己的 Claude Max/Pro 订阅登录"
|
||||||
Executable
+33
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
# .env 可选(订阅模式下完全无需 key)
|
||||||
|
if [[ ! -f .env ]]; then
|
||||||
|
cp .env.example .env
|
||||||
|
echo "已创建 .env(订阅模式无需填 key,直接继续)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 首次构建提示
|
||||||
|
if ! docker image inspect claude-agent-6repos:latest >/dev/null 2>&1; then
|
||||||
|
echo ">>> 首次构建镜像(约 5 分钟,下载 Node/Python/Go/Bun 工具链)"
|
||||||
|
docker compose build
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查容器内是否已登录(claude-home 卷里有 .credentials.json)
|
||||||
|
LOGGED_IN=$(docker volume inspect ai-ops_claude-home >/dev/null 2>&1 \
|
||||||
|
&& docker run --rm -v ai-ops_claude-home:/h alpine \
|
||||||
|
sh -c 'test -f /h/.credentials.json && echo yes || echo no' 2>/dev/null || echo no)
|
||||||
|
|
||||||
|
if [[ "$LOGGED_IN" != "yes" && -z "${ANTHROPIC_API_KEY:-$(grep -E '^ANTHROPIC_API_KEY=sk-' .env 2>/dev/null || true)}" ]]; then
|
||||||
|
cat <<'EOF'
|
||||||
|
|
||||||
|
>>> 首次登录提示:
|
||||||
|
进入容器后执行 /login,用浏览器完成 Claude Max 订阅 OAuth。
|
||||||
|
凭证会持久化到 docker volume,下次直接复用。
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec docker compose run --rm claude-agent "$@"
|
||||||
Executable
+13
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# 非交互跑单任务:./scripts/run-task.sh "审计 6 个仓库的过时依赖并提 PR"
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
echo "用法: $0 '<任务描述>'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose run --rm claude-agent \
|
||||||
|
claude -p "$1" --permission-mode acceptEdits
|
||||||
Reference in New Issue
Block a user