coderfleet 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coderfleet-0.1.1/.github/workflows/docs.yml +56 -0
- coderfleet-0.1.1/.github/workflows/release.yml +89 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/.gitignore +2 -0
- {coderfleet-0.1.0/coderfleet/data → coderfleet-0.1.1}/Dockerfile +5 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/PKG-INFO +26 -11
- {coderfleet-0.1.0 → coderfleet-0.1.1}/README.md +24 -10
- {coderfleet-0.1.0 → coderfleet-0.1.1}/accounts.conf.example +7 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/cli.py +1 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/compose.py +16 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/config_cmds.py +6 -6
- {coderfleet-0.1.0 → coderfleet-0.1.1/coderfleet/data}/Dockerfile +5 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/accounts.conf.example +7 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/entrypoint.sh +10 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/init_wizard.py +1 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/login_cmd.py +24 -3
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/main.py +207 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/models.py +194 -2
- coderfleet-0.1.1/coderfleet/server/push_manager.py +140 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/scheduler.py +348 -2
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/css/main.css +850 -13
- coderfleet-0.1.1/coderfleet/server/static/css/renderer.css +341 -0
- coderfleet-0.1.1/coderfleet/server/static/icons/icon.svg +6 -0
- coderfleet-0.1.1/coderfleet/server/static/icons/logo-mark.png +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/index.html +201 -4
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/app.js +2 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/chat.js +134 -10
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/log.js +2 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/nav.js +4 -2
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/renderer.js +120 -4
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/state.js +41 -0
- coderfleet-0.1.1/coderfleet/server/static/js/workflows.js +1248 -0
- coderfleet-0.1.1/coderfleet/server/static/manifest.json +26 -0
- coderfleet-0.1.1/coderfleet/server/static/mobile.html +1169 -0
- coderfleet-0.1.1/coderfleet/server/static/sw.js +61 -0
- coderfleet-0.1.1/coderfleet/server/static/vendor/drawflow.min.css +1 -0
- coderfleet-0.1.1/coderfleet/server/static/vendor/drawflow.min.js +1 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/task_cmds.py +1 -1
- coderfleet-0.1.1/docs/accounts.md +72 -0
- coderfleet-0.1.1/docs/assets/logo-mark.png +0 -0
- coderfleet-0.1.1/docs/assets/logo.svg +5 -0
- coderfleet-0.1.1/docs/assets/screenshots/app-accounts.png +0 -0
- coderfleet-0.1.1/docs/assets/screenshots/app-chat.png +0 -0
- coderfleet-0.1.1/docs/assets/screenshots/app-projects.png +0 -0
- coderfleet-0.1.1/docs/assets/screenshots/app-tasks.png +0 -0
- coderfleet-0.1.1/docs/commands.md +50 -0
- coderfleet-0.1.1/docs/concepts.md +47 -0
- coderfleet-0.1.1/docs/configuration.md +62 -0
- coderfleet-0.1.1/docs/custom-image.md +34 -0
- coderfleet-0.1.1/docs/faq.md +29 -0
- coderfleet-0.1.1/docs/index.md +135 -0
- coderfleet-0.1.1/docs/install.md +58 -0
- coderfleet-0.1.1/docs/migration.md +89 -0
- coderfleet-0.1.1/docs/network.md +51 -0
- coderfleet-0.1.1/docs/projects.md +51 -0
- coderfleet-0.1.1/docs/quickstart.md +96 -0
- coderfleet-0.1.1/docs/requirements.txt +2 -0
- coderfleet-0.1.1/docs/server.md +45 -0
- coderfleet-0.1.1/docs/stylesheets/extra.css +202 -0
- coderfleet-0.1.1/docs/tasks.md +67 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/entrypoint.sh +10 -0
- coderfleet-0.1.1/mkdocs.yml +80 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/pyproject.toml +2 -1
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tests/test_coderfleet_cli.py +47 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tests/test_scheduler.py +132 -0
- coderfleet-0.1.1/tests/test_static_ui.py +398 -0
- coderfleet-0.1.1/uv.lock +1631 -0
- coderfleet-0.1.0/tests/test_static_ui.py +0 -196
- {coderfleet-0.1.0 → coderfleet-0.1.1}/.github/workflows/publish.yml +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/CLAUDE.md +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/changelog/migrate-from-aicm-to-coderfleet.md +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/__init__.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/__main__.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/config.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/__init__.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/config.conf.example +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/projects.conf.example +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/data/scripts/coderfleet_usage_status.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/docker_ops.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/__init__.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/docker_mgr.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/accounts.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/projects.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/submit.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/tasks.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/terminal.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/js/utils.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/vendor/marked.min.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/vendor/xterm/addon-fit.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/vendor/xterm/xterm.css +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/static/vendor/xterm/xterm.js +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/coderfleet/server/terminal.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/config.conf.example +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/conversations/.gitkeep +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/projects.conf.example +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/scripts/coderfleet_usage_status.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tasks/.gitkeep +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tests/conftest.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tests/test_terminal.py +0 -0
- {coderfleet-0.1.0 → coderfleet-0.1.1}/tests/test_usage_status_script.py +0 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Deploy documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- "docs/**"
|
|
9
|
+
- "mkdocs.yml"
|
|
10
|
+
- ".github/workflows/docs.yml"
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
pages: write
|
|
16
|
+
id-token: write
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: pages
|
|
20
|
+
cancel-in-progress: false
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Check out repository
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.12"
|
|
33
|
+
|
|
34
|
+
- name: Install documentation dependencies
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
python -m pip install -r docs/requirements.txt
|
|
38
|
+
|
|
39
|
+
- name: Build site
|
|
40
|
+
run: mkdocs build --strict
|
|
41
|
+
|
|
42
|
+
- name: Upload artifact
|
|
43
|
+
uses: actions/upload-pages-artifact@v3
|
|
44
|
+
with:
|
|
45
|
+
path: site
|
|
46
|
+
|
|
47
|
+
deploy:
|
|
48
|
+
environment:
|
|
49
|
+
name: github-pages
|
|
50
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
needs: build
|
|
53
|
+
steps:
|
|
54
|
+
- name: Deploy to GitHub Pages
|
|
55
|
+
id: deployment
|
|
56
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
bump:
|
|
7
|
+
description: 'Next dev version bump after this release'
|
|
8
|
+
required: true
|
|
9
|
+
default: patch
|
|
10
|
+
type: choice
|
|
11
|
+
options:
|
|
12
|
+
- patch
|
|
13
|
+
- minor
|
|
14
|
+
- major
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: write
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
release:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout main
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
with:
|
|
26
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
fetch-depth: 0
|
|
28
|
+
|
|
29
|
+
- name: Set up Python
|
|
30
|
+
uses: actions/setup-python@v5
|
|
31
|
+
with:
|
|
32
|
+
python-version: '3.12'
|
|
33
|
+
|
|
34
|
+
- name: Compute versions
|
|
35
|
+
id: ver
|
|
36
|
+
env:
|
|
37
|
+
BUMP: ${{ inputs.bump }}
|
|
38
|
+
run: |
|
|
39
|
+
python - <<'PY'
|
|
40
|
+
import re, os, tomllib
|
|
41
|
+
from pathlib import Path
|
|
42
|
+
|
|
43
|
+
raw = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
|
|
44
|
+
m = re.match(r'^(\d+)\.(\d+)\.(\d+)(?:\.dev\d+)?$', raw)
|
|
45
|
+
if not m:
|
|
46
|
+
raise SystemExit(f"Cannot parse version: {raw!r}")
|
|
47
|
+
major, minor, patch = map(int, m.groups())
|
|
48
|
+
release = f"{major}.{minor}.{patch}"
|
|
49
|
+
|
|
50
|
+
bump = os.environ["BUMP"]
|
|
51
|
+
if bump == "major":
|
|
52
|
+
nxt = f"{major+1}.0.0.dev0"
|
|
53
|
+
elif bump == "minor":
|
|
54
|
+
nxt = f"{major}.{minor+1}.0.dev0"
|
|
55
|
+
else:
|
|
56
|
+
nxt = f"{major}.{minor}.{patch+1}.dev0"
|
|
57
|
+
|
|
58
|
+
Path(os.environ["GITHUB_OUTPUT"]).open("a").write(
|
|
59
|
+
f"release={release}\ntag=v{release}\nnext={nxt}\n"
|
|
60
|
+
)
|
|
61
|
+
PY
|
|
62
|
+
|
|
63
|
+
- name: Configure git
|
|
64
|
+
run: |
|
|
65
|
+
git config user.name "github-actions[bot]"
|
|
66
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
67
|
+
|
|
68
|
+
- name: Set release version
|
|
69
|
+
run: |
|
|
70
|
+
sed -i 's/^version = .*/version = "${{ steps.ver.outputs.release }}"/' pyproject.toml
|
|
71
|
+
git add pyproject.toml
|
|
72
|
+
git diff --cached --quiet || git commit -m "release: v${{ steps.ver.outputs.release }}"
|
|
73
|
+
git push origin main
|
|
74
|
+
|
|
75
|
+
- name: Create GitHub Release
|
|
76
|
+
env:
|
|
77
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
78
|
+
run: |
|
|
79
|
+
gh release create ${{ steps.ver.outputs.tag }} \
|
|
80
|
+
--title "v${{ steps.ver.outputs.release }}" \
|
|
81
|
+
--generate-notes \
|
|
82
|
+
--latest
|
|
83
|
+
|
|
84
|
+
- name: Bump to next dev version
|
|
85
|
+
run: |
|
|
86
|
+
sed -i 's/^version = .*/version = "${{ steps.ver.outputs.next }}"/' pyproject.toml
|
|
87
|
+
git add pyproject.toml
|
|
88
|
+
git commit -m "chore: bump to ${{ steps.ver.outputs.next }}"
|
|
89
|
+
git push origin main
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ============================================================
|
|
2
2
|
# CoderFleet — 统一工作容器镜像
|
|
3
|
-
# 包含:Python 3.12 / Node.js 20 / Codex CLI / Claude Code
|
|
3
|
+
# 包含:Python 3.12 / Node.js 20 / Codex CLI / Claude Code / OpenCode
|
|
4
4
|
# 平台:linux/amd64(Apple Silicon 通过 Docker 模拟运行)
|
|
5
5
|
# ============================================================
|
|
6
6
|
|
|
@@ -55,6 +55,9 @@ RUN npm install -g @openai/codex
|
|
|
55
55
|
# ── Claude Code CLI ───────────────────────────────────────
|
|
56
56
|
RUN npm install -g @anthropic-ai/claude-code
|
|
57
57
|
|
|
58
|
+
# ── OpenCode CLI ──────────────────────────────────────────
|
|
59
|
+
RUN npm install -g opencode-ai@latest
|
|
60
|
+
|
|
58
61
|
# ── Rust 1.93.0 ───────────────────────────────────────────
|
|
59
62
|
ENV RUSTUP_HOME=/usr/local/rustup \
|
|
60
63
|
CARGO_HOME=/usr/local/cargo \
|
|
@@ -75,6 +78,7 @@ WORKDIR /workspace
|
|
|
75
78
|
# 这两个目录由 CoderFleet 按账号挂载,容器内路径固定
|
|
76
79
|
# Codex 认证:/home/byclaw/.codex 由 CODEX_HOME 控制
|
|
77
80
|
# Claude 认证:/home/byclaw/.claude 由 CLAUDE_CONFIG_DIR 控制
|
|
81
|
+
# OpenCode 数据:/home/byclaw/.opencode(运行时按账号挂载并设置 XDG_*_HOME)
|
|
78
82
|
ENV CODEX_HOME=/home/byclaw/.codex
|
|
79
83
|
ENV CLAUDE_CONFIG_DIR=/home/byclaw/.claude
|
|
80
84
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coderfleet
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: CoderFleet - Run multiple Claude Code/Codex accounts in isolated Docker containers
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: aiofiles==24.1.0
|
|
@@ -9,6 +9,7 @@ Requires-Dist: fastapi==0.115.0
|
|
|
9
9
|
Requires-Dist: httpx>=0.27
|
|
10
10
|
Requires-Dist: pydantic==2.9.2
|
|
11
11
|
Requires-Dist: python-multipart==0.0.9
|
|
12
|
+
Requires-Dist: pywebpush>=2.0.0
|
|
12
13
|
Requires-Dist: pyyaml>=6.0
|
|
13
14
|
Requires-Dist: uvicorn[standard]==0.30.6
|
|
14
15
|
Description-Content-Type: text/markdown
|
|
@@ -21,14 +22,14 @@ Description-Content-Type: text/markdown
|
|
|
21
22
|
|
|
22
23
|
### 💡 为什么需要 CoderFleet?
|
|
23
24
|
|
|
24
|
-
在重度 AI 编程开发中,大模型 CLI(如 Claude Code、Codex)经常面临尴尬的使用瓶颈:
|
|
25
|
+
在重度 AI 编程开发中,大模型 CLI(如 Claude Code、Codex、OpenCode)经常面临尴尬的使用瓶颈:
|
|
25
26
|
* **单账号(Plus 会员)的额度不够用**,频繁遭遇大模型服务商的 Rate Limit 或当日使用上限;
|
|
26
27
|
* **高倍数套餐(如 5x/10x/20x 的账号会员)又极其昂贵**,在周期内往往使用量根本用不完,性价比极低;
|
|
27
28
|
* 最优解通常是**自己申请 2 个或多个普通/Plus 账号轮流使用**,但在单台机器上频繁切换账号、管理认证数据、以及维护隔离的网络环境极其繁杂。
|
|
28
29
|
|
|
29
30
|
**CoderFleet 正是为此而生!**
|
|
30
31
|
|
|
31
|
-
它允许你在单台宿主机上同时运行多个 **Codex CLI** 和 **
|
|
32
|
+
它允许你在单台宿主机上同时运行多个 **Codex CLI**、**Claude Code** 和 **OpenCode** 账号。每个账号采用独立容器隔离、独立会话认证,并设计了严密的**物理内网中继代理(gost)**网络,确保所有网络出站流量强制且唯一地走宿主机代理出口,完美解决国内开发者在调用 Claude / OpenAI 服务时遭遇的网络封锁和封号风险,实现"多账号额度无缝叠加、轮询提效"。
|
|
32
33
|
|
|
33
34
|
---
|
|
34
35
|
|
|
@@ -137,6 +138,7 @@ coderfleet build
|
|
|
137
138
|
- Rust 1.93.0
|
|
138
139
|
- Codex CLI(`@openai/codex`)
|
|
139
140
|
- Claude Code(`@anthropic-ai/claude-code`)
|
|
141
|
+
- OpenCode(`opencode-ai`)
|
|
140
142
|
|
|
141
143
|
### 3. 添加账号与项目
|
|
142
144
|
|
|
@@ -148,6 +150,10 @@ coderfleet project add app-a alice ~/projects/app-a
|
|
|
148
150
|
# Claude Code 账号
|
|
149
151
|
coderfleet account add bob TYPE=claude
|
|
150
152
|
coderfleet project add app-b bob ~/projects/app-b
|
|
153
|
+
|
|
154
|
+
# OpenCode 账号
|
|
155
|
+
coderfleet account add carol TYPE=opencode
|
|
156
|
+
coderfleet project add app-c carol ~/projects/app-c
|
|
151
157
|
```
|
|
152
158
|
|
|
153
159
|
### 4. 生成配置并启动容器
|
|
@@ -172,6 +178,7 @@ CLI 会输出授权 URL,在宿主机浏览器打开 → 完成授权 → 复
|
|
|
172
178
|
# 打开多个终端
|
|
173
179
|
coderfleet enter app-a # 进入 app-a 项目容器(使用 Codex 账号 alice)
|
|
174
180
|
coderfleet enter app-b # 进入 app-b 项目容器(使用 Claude Code 账号 bob)
|
|
181
|
+
coderfleet enter app-c # 进入 app-c 项目容器(使用 OpenCode 账号 carol)
|
|
175
182
|
```
|
|
176
183
|
|
|
177
184
|
进入后使用对应 CLI:
|
|
@@ -182,6 +189,9 @@ codex "帮我实现用户认证模块"
|
|
|
182
189
|
|
|
183
190
|
# Claude Code 容器内
|
|
184
191
|
claude "帮我重构这个函数"
|
|
192
|
+
|
|
193
|
+
# OpenCode 容器内
|
|
194
|
+
opencode run "帮我修复测试"
|
|
185
195
|
```
|
|
186
196
|
|
|
187
197
|
### 7. 启动调度服务与 Web 控制台
|
|
@@ -239,7 +249,7 @@ coderfleet task logs <任务ID> -f
|
|
|
239
249
|
|
|
240
250
|
| 命令 | 说明 |
|
|
241
251
|
|------|------|
|
|
242
|
-
| `coderfleet account add <名称> TYPE=codex\|claude [--auth env] [--env-file 路径] [--proxy relay\|off]` | 添加账号 |
|
|
252
|
+
| `coderfleet account add <名称> TYPE=codex\|claude\|opencode [--auth env] [--env-file 路径] [--proxy relay\|off]` | 添加账号 |
|
|
243
253
|
| `coderfleet account remove <名称>` | 删除账号(自动停止关联容器) |
|
|
244
254
|
| `coderfleet account list` | 列出所有账号及运行状态 |
|
|
245
255
|
| `coderfleet login <账号名\|all>` | 登录账号并持久化认证文件 |
|
|
@@ -302,10 +312,12 @@ RELAY_IMAGE=gogost/gost:3
|
|
|
302
312
|
### accounts.conf
|
|
303
313
|
|
|
304
314
|
```conf
|
|
305
|
-
# 格式:NAME=<名称> TYPE=codex|claude [AUTH=login|env] [ENV_FILE=路径] [PROXY=relay|off]
|
|
315
|
+
# 格式:NAME=<名称> TYPE=codex|claude|opencode [AUTH=login|env] [ENV_FILE=路径] [PROXY=relay|off]
|
|
306
316
|
NAME=alice TYPE=codex
|
|
307
317
|
NAME=bob TYPE=claude
|
|
318
|
+
NAME=carol TYPE=opencode
|
|
308
319
|
NAME=claude-api TYPE=claude AUTH=env ENV_FILE=./accounts/claude-api/env
|
|
320
|
+
NAME=opencode-api TYPE=opencode AUTH=env ENV_FILE=./accounts/opencode-api/env
|
|
309
321
|
NAME=local TYPE=claude PROXY=off
|
|
310
322
|
```
|
|
311
323
|
|
|
@@ -314,16 +326,17 @@ NAME=local TYPE=claude PROXY=off
|
|
|
314
326
|
| 字段 | 必填 | 说明 |
|
|
315
327
|
|------|------|------|
|
|
316
328
|
| `NAME` | 是 | 账号名,只允许字母/数字/连字符 |
|
|
317
|
-
| `TYPE` | 是 | `codex` 使用 Codex CLI,`claude` 使用 Claude Code |
|
|
318
|
-
| `AUTH` | 否 | 认证方式,默认 `login`;Claude Code 可用 `env` 通过 API Key 认证 |
|
|
329
|
+
| `TYPE` | 是 | `codex` 使用 Codex CLI,`claude` 使用 Claude Code,`opencode` 使用 OpenCode |
|
|
330
|
+
| `AUTH` | 否 | 认证方式,默认 `login`;Claude Code / OpenCode 可用 `env` 通过 API Key 认证 |
|
|
319
331
|
| `ENV_FILE` | 否 | Docker Compose env_file 路径;`AUTH=env` 时省略则默认 `./accounts/<名称>/env` |
|
|
320
332
|
| `PROXY` | 否 | 默认 `relay`(走代理中继);`off` 表示不注入代理变量,连接普通网络 |
|
|
321
333
|
|
|
322
|
-
`AUTH=env` 用于 Claude Code API key 场景:
|
|
334
|
+
`AUTH=env` 用于 Claude Code / OpenCode API key 场景:
|
|
323
335
|
|
|
324
336
|
```bash
|
|
325
337
|
coderfleet account add claude-api TYPE=claude --auth env
|
|
326
|
-
|
|
338
|
+
coderfleet account add opencode-api TYPE=opencode --auth env
|
|
339
|
+
# 然后编辑对应的 ~/.coderfleet/accounts/<账号名>/env
|
|
327
340
|
```
|
|
328
341
|
|
|
329
342
|
示例 env 文件:
|
|
@@ -333,7 +346,7 @@ ANTHROPIC_API_KEY=sk-ant-...
|
|
|
333
346
|
# ANTHROPIC_BASE_URL=https://api.anthropic.com
|
|
334
347
|
```
|
|
335
348
|
|
|
336
|
-
> 注意:Claude Code 会优先使用 `ANTHROPIC_API_KEY
|
|
349
|
+
> 注意:Claude Code 会优先使用 `ANTHROPIC_API_KEY`;OpenCode 会读取环境变量和项目 `.env` 中的 provider API key;`login all` 会自动跳过 `AUTH=env` 账号。
|
|
337
350
|
|
|
338
351
|
### projects.conf
|
|
339
352
|
|
|
@@ -400,13 +413,15 @@ coderfleet check-proxy
|
|
|
400
413
|
|
|
401
414
|
## 认证机制
|
|
402
415
|
|
|
403
|
-
|
|
416
|
+
三种 CLI 的认证目录挂载方式:
|
|
404
417
|
|
|
405
418
|
| CLI | 认证目录(容器内) | 本地存储 |
|
|
406
419
|
|-----|--------------------|----------|
|
|
407
420
|
| Codex | `/home/byclaw/.codex` | `accounts/<名称>/` |
|
|
408
421
|
| Claude Code | `/home/byclaw/.claude` | `accounts/<名称>/` |
|
|
409
422
|
| Claude Code API key | 同上 | `ENV_FILE` 指定文件 |
|
|
423
|
+
| OpenCode | `/home/byclaw/.opencode`(内部设置 XDG data/config/state/cache) | `accounts/<名称>/` |
|
|
424
|
+
| OpenCode API key | 环境变量 | `ENV_FILE` 指定文件 |
|
|
410
425
|
|
|
411
426
|
每个账号的认证数据独立存储,容器删除重建后无需重新登录。
|
|
412
427
|
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
### 💡 为什么需要 CoderFleet?
|
|
8
8
|
|
|
9
|
-
在重度 AI 编程开发中,大模型 CLI(如 Claude Code、Codex)经常面临尴尬的使用瓶颈:
|
|
9
|
+
在重度 AI 编程开发中,大模型 CLI(如 Claude Code、Codex、OpenCode)经常面临尴尬的使用瓶颈:
|
|
10
10
|
* **单账号(Plus 会员)的额度不够用**,频繁遭遇大模型服务商的 Rate Limit 或当日使用上限;
|
|
11
11
|
* **高倍数套餐(如 5x/10x/20x 的账号会员)又极其昂贵**,在周期内往往使用量根本用不完,性价比极低;
|
|
12
12
|
* 最优解通常是**自己申请 2 个或多个普通/Plus 账号轮流使用**,但在单台机器上频繁切换账号、管理认证数据、以及维护隔离的网络环境极其繁杂。
|
|
13
13
|
|
|
14
14
|
**CoderFleet 正是为此而生!**
|
|
15
15
|
|
|
16
|
-
它允许你在单台宿主机上同时运行多个 **Codex CLI** 和 **
|
|
16
|
+
它允许你在单台宿主机上同时运行多个 **Codex CLI**、**Claude Code** 和 **OpenCode** 账号。每个账号采用独立容器隔离、独立会话认证,并设计了严密的**物理内网中继代理(gost)**网络,确保所有网络出站流量强制且唯一地走宿主机代理出口,完美解决国内开发者在调用 Claude / OpenAI 服务时遭遇的网络封锁和封号风险,实现"多账号额度无缝叠加、轮询提效"。
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -122,6 +122,7 @@ coderfleet build
|
|
|
122
122
|
- Rust 1.93.0
|
|
123
123
|
- Codex CLI(`@openai/codex`)
|
|
124
124
|
- Claude Code(`@anthropic-ai/claude-code`)
|
|
125
|
+
- OpenCode(`opencode-ai`)
|
|
125
126
|
|
|
126
127
|
### 3. 添加账号与项目
|
|
127
128
|
|
|
@@ -133,6 +134,10 @@ coderfleet project add app-a alice ~/projects/app-a
|
|
|
133
134
|
# Claude Code 账号
|
|
134
135
|
coderfleet account add bob TYPE=claude
|
|
135
136
|
coderfleet project add app-b bob ~/projects/app-b
|
|
137
|
+
|
|
138
|
+
# OpenCode 账号
|
|
139
|
+
coderfleet account add carol TYPE=opencode
|
|
140
|
+
coderfleet project add app-c carol ~/projects/app-c
|
|
136
141
|
```
|
|
137
142
|
|
|
138
143
|
### 4. 生成配置并启动容器
|
|
@@ -157,6 +162,7 @@ CLI 会输出授权 URL,在宿主机浏览器打开 → 完成授权 → 复
|
|
|
157
162
|
# 打开多个终端
|
|
158
163
|
coderfleet enter app-a # 进入 app-a 项目容器(使用 Codex 账号 alice)
|
|
159
164
|
coderfleet enter app-b # 进入 app-b 项目容器(使用 Claude Code 账号 bob)
|
|
165
|
+
coderfleet enter app-c # 进入 app-c 项目容器(使用 OpenCode 账号 carol)
|
|
160
166
|
```
|
|
161
167
|
|
|
162
168
|
进入后使用对应 CLI:
|
|
@@ -167,6 +173,9 @@ codex "帮我实现用户认证模块"
|
|
|
167
173
|
|
|
168
174
|
# Claude Code 容器内
|
|
169
175
|
claude "帮我重构这个函数"
|
|
176
|
+
|
|
177
|
+
# OpenCode 容器内
|
|
178
|
+
opencode run "帮我修复测试"
|
|
170
179
|
```
|
|
171
180
|
|
|
172
181
|
### 7. 启动调度服务与 Web 控制台
|
|
@@ -224,7 +233,7 @@ coderfleet task logs <任务ID> -f
|
|
|
224
233
|
|
|
225
234
|
| 命令 | 说明 |
|
|
226
235
|
|------|------|
|
|
227
|
-
| `coderfleet account add <名称> TYPE=codex\|claude [--auth env] [--env-file 路径] [--proxy relay\|off]` | 添加账号 |
|
|
236
|
+
| `coderfleet account add <名称> TYPE=codex\|claude\|opencode [--auth env] [--env-file 路径] [--proxy relay\|off]` | 添加账号 |
|
|
228
237
|
| `coderfleet account remove <名称>` | 删除账号(自动停止关联容器) |
|
|
229
238
|
| `coderfleet account list` | 列出所有账号及运行状态 |
|
|
230
239
|
| `coderfleet login <账号名\|all>` | 登录账号并持久化认证文件 |
|
|
@@ -287,10 +296,12 @@ RELAY_IMAGE=gogost/gost:3
|
|
|
287
296
|
### accounts.conf
|
|
288
297
|
|
|
289
298
|
```conf
|
|
290
|
-
# 格式:NAME=<名称> TYPE=codex|claude [AUTH=login|env] [ENV_FILE=路径] [PROXY=relay|off]
|
|
299
|
+
# 格式:NAME=<名称> TYPE=codex|claude|opencode [AUTH=login|env] [ENV_FILE=路径] [PROXY=relay|off]
|
|
291
300
|
NAME=alice TYPE=codex
|
|
292
301
|
NAME=bob TYPE=claude
|
|
302
|
+
NAME=carol TYPE=opencode
|
|
293
303
|
NAME=claude-api TYPE=claude AUTH=env ENV_FILE=./accounts/claude-api/env
|
|
304
|
+
NAME=opencode-api TYPE=opencode AUTH=env ENV_FILE=./accounts/opencode-api/env
|
|
294
305
|
NAME=local TYPE=claude PROXY=off
|
|
295
306
|
```
|
|
296
307
|
|
|
@@ -299,16 +310,17 @@ NAME=local TYPE=claude PROXY=off
|
|
|
299
310
|
| 字段 | 必填 | 说明 |
|
|
300
311
|
|------|------|------|
|
|
301
312
|
| `NAME` | 是 | 账号名,只允许字母/数字/连字符 |
|
|
302
|
-
| `TYPE` | 是 | `codex` 使用 Codex CLI,`claude` 使用 Claude Code |
|
|
303
|
-
| `AUTH` | 否 | 认证方式,默认 `login`;Claude Code 可用 `env` 通过 API Key 认证 |
|
|
313
|
+
| `TYPE` | 是 | `codex` 使用 Codex CLI,`claude` 使用 Claude Code,`opencode` 使用 OpenCode |
|
|
314
|
+
| `AUTH` | 否 | 认证方式,默认 `login`;Claude Code / OpenCode 可用 `env` 通过 API Key 认证 |
|
|
304
315
|
| `ENV_FILE` | 否 | Docker Compose env_file 路径;`AUTH=env` 时省略则默认 `./accounts/<名称>/env` |
|
|
305
316
|
| `PROXY` | 否 | 默认 `relay`(走代理中继);`off` 表示不注入代理变量,连接普通网络 |
|
|
306
317
|
|
|
307
|
-
`AUTH=env` 用于 Claude Code API key 场景:
|
|
318
|
+
`AUTH=env` 用于 Claude Code / OpenCode API key 场景:
|
|
308
319
|
|
|
309
320
|
```bash
|
|
310
321
|
coderfleet account add claude-api TYPE=claude --auth env
|
|
311
|
-
|
|
322
|
+
coderfleet account add opencode-api TYPE=opencode --auth env
|
|
323
|
+
# 然后编辑对应的 ~/.coderfleet/accounts/<账号名>/env
|
|
312
324
|
```
|
|
313
325
|
|
|
314
326
|
示例 env 文件:
|
|
@@ -318,7 +330,7 @@ ANTHROPIC_API_KEY=sk-ant-...
|
|
|
318
330
|
# ANTHROPIC_BASE_URL=https://api.anthropic.com
|
|
319
331
|
```
|
|
320
332
|
|
|
321
|
-
> 注意:Claude Code 会优先使用 `ANTHROPIC_API_KEY
|
|
333
|
+
> 注意:Claude Code 会优先使用 `ANTHROPIC_API_KEY`;OpenCode 会读取环境变量和项目 `.env` 中的 provider API key;`login all` 会自动跳过 `AUTH=env` 账号。
|
|
322
334
|
|
|
323
335
|
### projects.conf
|
|
324
336
|
|
|
@@ -385,13 +397,15 @@ coderfleet check-proxy
|
|
|
385
397
|
|
|
386
398
|
## 认证机制
|
|
387
399
|
|
|
388
|
-
|
|
400
|
+
三种 CLI 的认证目录挂载方式:
|
|
389
401
|
|
|
390
402
|
| CLI | 认证目录(容器内) | 本地存储 |
|
|
391
403
|
|-----|--------------------|----------|
|
|
392
404
|
| Codex | `/home/byclaw/.codex` | `accounts/<名称>/` |
|
|
393
405
|
| Claude Code | `/home/byclaw/.claude` | `accounts/<名称>/` |
|
|
394
406
|
| Claude Code API key | 同上 | `ENV_FILE` 指定文件 |
|
|
407
|
+
| OpenCode | `/home/byclaw/.opencode`(内部设置 XDG data/config/state/cache) | `accounts/<名称>/` |
|
|
408
|
+
| OpenCode API key | 环境变量 | `ENV_FILE` 指定文件 |
|
|
395
409
|
|
|
396
410
|
每个账号的认证数据独立存储,容器删除重建后无需重新登录。
|
|
397
411
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# 字段说明:
|
|
5
5
|
# NAME=<名称> 必填,只允许字母/数字/连字符
|
|
6
|
-
# TYPE=codex|claude
|
|
6
|
+
# TYPE=codex|claude|opencode 必填,使用哪个 AI CLI
|
|
7
7
|
# AUTH=login|env 可选,默认 login
|
|
8
8
|
# ENV_FILE=<路径> AUTH=env 时可选;省略则默认 ./accounts/<名称>/env
|
|
9
9
|
# PROXY=relay|off 可选,默认 relay;off 表示该账号下项目不注入代理
|
|
@@ -18,9 +18,15 @@
|
|
|
18
18
|
# Claude Code 账号示例
|
|
19
19
|
# NAME=claude-alice TYPE=claude
|
|
20
20
|
|
|
21
|
+
# OpenCode 账号示例
|
|
22
|
+
# NAME=opencode-alice TYPE=opencode
|
|
23
|
+
|
|
21
24
|
# Claude Code 环境变量认证示例(API key 会优先于订阅登录态)
|
|
22
25
|
# NAME=claude-api TYPE=claude AUTH=env
|
|
23
26
|
# NAME=claude-api TYPE=claude AUTH=env ENV_FILE=./accounts/claude-api/env
|
|
24
27
|
|
|
28
|
+
# OpenCode 环境变量认证示例(可在 env 文件中配置各 provider API key)
|
|
29
|
+
# NAME=opencode-api TYPE=opencode AUTH=env
|
|
30
|
+
|
|
25
31
|
# 不走代理的账号示例(该账号关联的项目都会直连)
|
|
26
32
|
# NAME=claude-local TYPE=claude PROXY=off
|
|
@@ -113,7 +113,7 @@ def _server_status(ws: Path) -> None:
|
|
|
113
113
|
def main(ctx: click.Context) -> None:
|
|
114
114
|
"""CoderFleet
|
|
115
115
|
|
|
116
|
-
Manages multiple Claude Code / Codex accounts in isolated Docker containers.
|
|
116
|
+
Manages multiple Claude Code / Codex / OpenCode accounts in isolated Docker containers.
|
|
117
117
|
|
|
118
118
|
Workspace location: CODERFLEET_WORKSPACE env var, or ~/.coderfleet/ by default.
|
|
119
119
|
"""
|
|
@@ -14,6 +14,13 @@ import yaml
|
|
|
14
14
|
from coderfleet.config import load_config, parse_conf
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
AUTH_DIRS = {
|
|
18
|
+
"codex": "/home/byclaw/.codex",
|
|
19
|
+
"claude": "/home/byclaw/.claude",
|
|
20
|
+
"opencode": "/home/byclaw/.opencode",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
17
24
|
def _make_dumper() -> type[yaml.Dumper]:
|
|
18
25
|
"""Return a YAML Dumper that quotes YAML-1.1 boolean-ambiguous strings."""
|
|
19
26
|
_BOOL_LIKE = frozenset(["off", "on", "yes", "no", "true", "false", "null", "~"])
|
|
@@ -94,7 +101,7 @@ def generate_compose(ws: Path) -> dict[str, Any]:
|
|
|
94
101
|
svc_name = f"{acc_type}-project-{pname}"
|
|
95
102
|
ctr_name = f"{acc_type}-{pname}"
|
|
96
103
|
auth_src = f"./accounts/{paccount}"
|
|
97
|
-
auth_dst =
|
|
104
|
+
auth_dst = AUTH_DIRS.get(acc_type, "/home/byclaw/.codex")
|
|
98
105
|
|
|
99
106
|
(ws / "accounts" / paccount).mkdir(parents=True, exist_ok=True)
|
|
100
107
|
|
|
@@ -107,6 +114,14 @@ def generate_compose(ws: Path) -> dict[str, Any]:
|
|
|
107
114
|
"CODERFLEET_ACCOUNT_PROXY": acc_proxy,
|
|
108
115
|
}
|
|
109
116
|
|
|
117
|
+
if acc_type == "opencode":
|
|
118
|
+
environment.update({
|
|
119
|
+
"XDG_DATA_HOME": "/home/byclaw/.opencode/data",
|
|
120
|
+
"XDG_CONFIG_HOME": "/home/byclaw/.opencode/config",
|
|
121
|
+
"XDG_STATE_HOME": "/home/byclaw/.opencode/state",
|
|
122
|
+
"XDG_CACHE_HOME": "/home/byclaw/.opencode/cache",
|
|
123
|
+
})
|
|
124
|
+
|
|
110
125
|
if acc_proxy != "off":
|
|
111
126
|
environment.update({
|
|
112
127
|
"HTTP_PROXY": proxy_url,
|
|
@@ -38,7 +38,7 @@ def account_group() -> None:
|
|
|
38
38
|
|
|
39
39
|
@account_group.command("add")
|
|
40
40
|
@click.argument("name")
|
|
41
|
-
@click.argument("typearg", metavar="TYPE=codex|claude")
|
|
41
|
+
@click.argument("typearg", metavar="TYPE=codex|claude|opencode")
|
|
42
42
|
@click.option("--auth", default="login", type=click.Choice(["login", "env"]),
|
|
43
43
|
show_default=True, help="Authentication method")
|
|
44
44
|
@click.option("--env-file", "env_file", default=None,
|
|
@@ -54,19 +54,19 @@ def cmd_account_add(
|
|
|
54
54
|
env_file: Optional[str],
|
|
55
55
|
proxy: str,
|
|
56
56
|
) -> None:
|
|
57
|
-
"""Add a new account. TYPE=codex|claude (or just codex|claude)."""
|
|
57
|
+
"""Add a new account. TYPE=codex|claude|opencode (or just codex|claude|opencode)."""
|
|
58
58
|
ws: Path = ctx.obj["workspace"]
|
|
59
59
|
|
|
60
60
|
if not _NAME_RE.match(name):
|
|
61
61
|
raise click.ClickException("NAME 只能包含字母、数字、连字符")
|
|
62
62
|
|
|
63
63
|
acc_type = typearg[5:] if typearg.startswith("TYPE=") else typearg
|
|
64
|
-
if acc_type not in ("codex", "claude"):
|
|
65
|
-
raise click.ClickException("TYPE 不合法,只支持 TYPE=codex 或 TYPE=
|
|
64
|
+
if acc_type not in ("codex", "claude", "opencode"):
|
|
65
|
+
raise click.ClickException("TYPE 不合法,只支持 TYPE=codex、TYPE=claude 或 TYPE=opencode")
|
|
66
66
|
|
|
67
67
|
if auth == "env":
|
|
68
|
-
if acc_type
|
|
69
|
-
raise click.ClickException("AUTH=env 目前只支持 TYPE=claude")
|
|
68
|
+
if acc_type not in ("claude", "opencode"):
|
|
69
|
+
raise click.ClickException("AUTH=env 目前只支持 TYPE=claude 或 TYPE=opencode")
|
|
70
70
|
if not env_file:
|
|
71
71
|
env_file = f"./accounts/{name}/env"
|
|
72
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# ============================================================
|
|
2
2
|
# CoderFleet — 统一工作容器镜像
|
|
3
|
-
# 包含:Python 3.12 / Node.js 20 / Codex CLI / Claude Code
|
|
3
|
+
# 包含:Python 3.12 / Node.js 20 / Codex CLI / Claude Code / OpenCode
|
|
4
4
|
# 平台:linux/amd64(Apple Silicon 通过 Docker 模拟运行)
|
|
5
5
|
# ============================================================
|
|
6
6
|
|
|
@@ -55,6 +55,9 @@ RUN npm install -g @openai/codex
|
|
|
55
55
|
# ── Claude Code CLI ───────────────────────────────────────
|
|
56
56
|
RUN npm install -g @anthropic-ai/claude-code
|
|
57
57
|
|
|
58
|
+
# ── OpenCode CLI ──────────────────────────────────────────
|
|
59
|
+
RUN npm install -g opencode-ai@latest
|
|
60
|
+
|
|
58
61
|
# ── Rust 1.93.0 ───────────────────────────────────────────
|
|
59
62
|
ENV RUSTUP_HOME=/usr/local/rustup \
|
|
60
63
|
CARGO_HOME=/usr/local/cargo \
|
|
@@ -75,6 +78,7 @@ WORKDIR /workspace
|
|
|
75
78
|
# 这两个目录由 CoderFleet 按账号挂载,容器内路径固定
|
|
76
79
|
# Codex 认证:/home/byclaw/.codex 由 CODEX_HOME 控制
|
|
77
80
|
# Claude 认证:/home/byclaw/.claude 由 CLAUDE_CONFIG_DIR 控制
|
|
81
|
+
# OpenCode 数据:/home/byclaw/.opencode(运行时按账号挂载并设置 XDG_*_HOME)
|
|
78
82
|
ENV CODEX_HOME=/home/byclaw/.codex
|
|
79
83
|
ENV CLAUDE_CONFIG_DIR=/home/byclaw/.claude
|
|
80
84
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# 字段说明:
|
|
5
5
|
# NAME=<名称> 必填,只允许字母/数字/连字符
|
|
6
|
-
# TYPE=codex|claude
|
|
6
|
+
# TYPE=codex|claude|opencode 必填,使用哪个 AI CLI
|
|
7
7
|
# AUTH=login|env 可选,默认 login
|
|
8
8
|
# ENV_FILE=<路径> AUTH=env 时可选;省略则默认 ./accounts/<名称>/env
|
|
9
9
|
# PROXY=relay|off 可选,默认 relay;off 表示该账号下项目不注入代理
|
|
@@ -18,9 +18,15 @@
|
|
|
18
18
|
# Claude Code 账号示例
|
|
19
19
|
# NAME=claude-alice TYPE=claude
|
|
20
20
|
|
|
21
|
+
# OpenCode 账号示例
|
|
22
|
+
# NAME=opencode-alice TYPE=opencode
|
|
23
|
+
|
|
21
24
|
# Claude Code 环境变量认证示例(API key 会优先于订阅登录态)
|
|
22
25
|
# NAME=claude-api TYPE=claude AUTH=env
|
|
23
26
|
# NAME=claude-api TYPE=claude AUTH=env ENV_FILE=./accounts/claude-api/env
|
|
24
27
|
|
|
28
|
+
# OpenCode 环境变量认证示例(可在 env 文件中配置各 provider API key)
|
|
29
|
+
# NAME=opencode-api TYPE=opencode AUTH=env
|
|
30
|
+
|
|
25
31
|
# 不走代理的账号示例(该账号关联的项目都会直连)
|
|
26
32
|
# NAME=claude-local TYPE=claude PROXY=off
|
|
@@ -49,6 +49,16 @@ case "$ACCOUNT_TYPE" in
|
|
|
49
49
|
echo "Claude 环境变量认证:已启用"
|
|
50
50
|
fi
|
|
51
51
|
;;
|
|
52
|
+
opencode)
|
|
53
|
+
mkdir -p "${XDG_DATA_HOME:-/home/byclaw/.opencode/data}"
|
|
54
|
+
mkdir -p "${XDG_CONFIG_HOME:-/home/byclaw/.opencode/config}"
|
|
55
|
+
mkdir -p "${XDG_STATE_HOME:-/home/byclaw/.opencode/state}"
|
|
56
|
+
mkdir -p "${XDG_CACHE_HOME:-/home/byclaw/.opencode/cache}"
|
|
57
|
+
echo "OpenCode 数据目录:${XDG_DATA_HOME:-/home/byclaw/.opencode/data}"
|
|
58
|
+
if [ "${CODERFLEET_ACCOUNT_AUTH:-login}" = "env" ]; then
|
|
59
|
+
echo "OpenCode 环境变量认证:已启用"
|
|
60
|
+
fi
|
|
61
|
+
;;
|
|
52
62
|
esac
|
|
53
63
|
|
|
54
64
|
# ── 执行传入的命令(默认 sleep infinity)─────────────────
|
|
@@ -209,6 +209,7 @@ def _print_next_steps(ws: Path) -> None:
|
|
|
209
209
|
click.secho(f" coderfleet build", fg="cyan")
|
|
210
210
|
click.echo(f" 2. 添加账号:")
|
|
211
211
|
click.secho(f" coderfleet account add <名称> TYPE=claude", fg="cyan")
|
|
212
|
+
click.secho(f" coderfleet account add <名称> TYPE=opencode", fg="cyan")
|
|
212
213
|
click.echo(f" 3. 添加项目:")
|
|
213
214
|
click.secho(f" coderfleet project add <名称> <账号名> ~/projects/myproject", fg="cyan")
|
|
214
215
|
click.echo(f" 4. 应用配置并启动容器:")
|