@archships/seekcode-cli
v0.1.10
Published
AI-powered GitHub PR review CLI with multi-phase analysis, line-level suggestions, and structured reports
Readme
seekcode
AI 驱动的 GitHub PR 自动 review CLI。多阶段流水线分析每个 Pull Request,将结构化报告回写到 GitHub,可单次运行也可作为长跑 daemon。
目录
功能简介
Seekcode 自动审查 GitHub Pull Request。每次运行会:
- 拉取 PR diff 和元数据
- 执行本地规则检查 — 密钥检测、超大 diff、生成文件识别
- 加载
SOUL.md(如果存在)— 仓库自定义的审查准则 - 运行 5 阶段 LLM 审查流水线:
- Preflight — 文件评分,挑选优先级高的候选
- Shallow Review(>150 文件时切到 Large Review)— 浅层快速发现高价值问题
- Deep Dive(可选)— 对高风险文件深入分析
- Test Planning — 测试建议
- Description Summary — 简短摘要
- 将结构化报告回帖到 PR(重复审查时 upsert)
- 可选行级建议 — 用
suggestion代码块发送内联建议 - 状态去重 — 同一 commit 不会重复审查
兼容任何 OpenAI 兼容的 LLM endpoint(OpenAI、Azure、GLM、DeepSeek、本地 Ollama 等)。
支持 9 种输出语言:en、zh-CN、zh-TW、ja、es、fr、de、pt-BR、ko。
安装
npm install -g @archships/seekcode-cli前置依赖:
- Node.js 18 或更高
- GitHub 账号
- OpenAI 兼容的 LLM endpoint(带 API key)
验证安装:
seekcode --version快速开始
从零到第一次发表 review,最快路径:
# 1. 安装
npm install -g @archships/seekcode-cli
# 2. 运行交互式向导
seekcode init
# 3. 验证配置
seekcode status
# 4. 预演 review,不消耗 token
seekcode review --repo your-org/your-repo --pr 42 --dry-run
# 5. 实际运行 review 并发表到 GitHub
seekcode review --repo your-org/your-repo --pr 42 --post-commentinit 向导会引导你完成:
- GitHub OAuth 登录(Device Flow)— 浏览器输入 8 位激活码即可
- 安装 GitHub App 到你想 review 的仓库(自动打开安装页)
- 配置 LLM endpoint — base URL、API key、模型 ID
- 选择输出语言 — 默认英文
配置写入 ~/.seekcode/config.yml(mode 0600),后续命令自动发现,无需重复指定 --config。
命令参考
seekcode init
一站式交互式初始化。首次使用请先运行此命令。
seekcode init做什么:
- 通过 OAuth Device Flow 登录 GitHub(如未登录)
- 自动打开浏览器到 GitHub App 安装页
- 询问 LLM endpoint、API key、模型 ID、输出语言
- 写入
~/.seekcode/config.yml(mode 0600)
注意事项:
- 如果配置已存在会询问是否覆盖
- 已经跑过
seekcode login的话可以跳过 Step 1 - API key 以明文存储,请妥善保护配置文件权限
seekcode status
诊断命令。任何时候出问题都可以先运行这个,它显示 seekcode 知道的全部状态。
seekcode status输出示例:
✓ Authenticated
Source: OAuth (seekcode login) ← 当前生效的认证方式
Access token: in 7h ← 当前 token 还能用多久
Refresh token: in 182d ← 强制重新登录的截止时间
User: your-username
✓ Config: /Users/you/.seekcode/config.yml
Model: gpt-4o
Endpoint: https://api.openai.com/v1
Language: en
✓ LLM endpoint reachable (87 models available) ← 验证 baseUrl + apiKey 可达
📦 GitHub App installations (2):
• your-personal-account (3 repos): ← 已授权可审查的仓库
- your-personal-account/project-a
- your-personal-account/project-b
- your-personal-account/project-c
• your-org (15 repos):
- your-org/api-server
- your-org/web-frontend
...
Total: 18 reviewable repos
🤖 Last daemon round: ← 仅在 daemon 跑过后显示
Started: 2026-04-08T05:43:04Z
Finished: 2026-04-08T05:44:32Z
Repos: 15/15 succeeded
PRs: 3 reviewed, 12 skipped
Cost (last hour): $0.42可能看到的告警:
| 告警 | 含义 | 解决 |
|------|------|------|
| ✗ Not authenticated | 没有可用 token | seekcode login |
| ⚠️ Refresh token expires in Nd | 不到 14 天 | 安排重新登录 |
| ⚠️ LLM endpoint check failed | LLM API 不可达 | 检查 baseUrl、apiKey、网络 |
| ⚠️ API key not configured | 配置缺 agent.apiKey | 编辑配置文件 |
| 📦 No GitHub App installations | 没有装 App | 访问展示的安装 URL |
seekcode review
按需 review 单个 Pull Request。
seekcode review --repo OWNER/REPO --pr NUMBER [options]必填参数:
| 参数 | 说明 |
|------|------|
| --repo <owner/repo> | GitHub 仓库 |
| --pr <number> | PR 编号 |
可选参数:
| 参数 | 说明 | 默认 |
|------|------|------|
| --post-comment | 把审查报告发表到 PR | false |
| --dry-run | 不调 LLM 不发评论,仅显示预演 | false |
| --language <code> | 覆盖输出语言(en、zh-CN、ja 等) | 来自 config |
| --config <path> | 显式指定配置文件,跳过自动发现 | 自动 |
| --verbose / -v | 打印调试信息和完整异常栈 | false |
示例:
# 仅预演 — 不调 LLM 不写 GitHub(免费、可放心反复跑)
seekcode review --repo your-org/api --pr 42 --dry-run
# 运行 review,输出到终端,不发表到 GitHub
seekcode review --repo your-org/api --pr 42
# 运行 review 并发表报告到 GitHub
seekcode review --repo your-org/api --pr 42 --post-comment
# 临时覆盖语言
seekcode review --repo your-org/api --pr 42 --post-comment --language zh-CN
# 使用项目级配置(覆盖 ~/.seekcode/config.yml)
seekcode review --repo your-org/api --pr 42 --config ./seekcode.yml行为说明:
- 幂等 — 如果该 commit(
owner/repo + PR# + sha)已审查过,会显示⏭️ skipped。提交新 commit 会自动重新审查。 - 失败处理:
- LLM 调用失败 → 降级输出本地规则结果(如果有)
- 评论发表失败 → 状态不标记为已审查(下次重试)
- PR 不存在 → 友好错误说明可能原因
- 退出码: 成功或跳过为
0,硬失败为1
--dry-run 输出示例:
=== DRY RUN — no LLM call, no GitHub comment ===
PR: #42 Add user authentication
Author: alice
Branch: feat/auth → main
Files: 8 (7 reviewable, 1 binary)
SOUL.md: loaded
Estimated prompt tokens: ~12,400
Local rule findings: 1 (1 error, 0 warning, 0 info)
Rule findings:
[ERROR] Possible secret detected (src/auth/keys.ts)
Run without --dry-run to actually call the LLM and post the review.seekcode daemon
多仓库连续轮询,发现新 PR 自动 review。设计用于长跑后台服务。
seekcode daemon [仓库源] [options]仓库源 — 三选一:
# A. 单个仓库
seekcode daemon --repo your-org/api
# B. 显式列表(逗号分隔)
seekcode daemon --repos your-org/api,your-org/web,your-org/worker
# C. 自动发现所有装了 App 的仓库(运维场景推荐)
seekcode daemon --all-installed也可以在配置里设置(daemon.repos 或 daemon.allInstalled: true),命令行就可以省略。
可选参数:
| 参数 | 说明 | 默认 |
|------|------|------|
| --interval <seconds> | 两轮之间的间隔秒数 | 300(5 分钟) |
| --post-comment | 是否发表评论到 GitHub | true |
| --language <code> | 输出语言 | 来自 config |
| --config <path> | 显式配置文件路径 | 自动 |
多仓库行为:
- 失败隔离 — 单个仓库失败不影响其他仓库
- 并发控制 —
daemon.maxParallelRepos(默认 1,串行)控制单轮内并发仓库数 - 成本守卫 —
daemon.maxCostPerHourUsd在滚动 1 小时成本超限时跳过下一轮(需要设置agent.costPerMillionTokensUsd) - Token 自动续期 — OAuth token 在每个请求前自动检查并续期,daemon 可无人值守 6 个月
- 聚合状态 —
seekcode status显示最近一轮的统计
优雅停止:
发送 SIGTERM 信号(前台运行时按 Ctrl+C)。daemon 会完成当前 PR 后退出。
# 前台运行
seekcode daemon --all-installed
# 后台运行(生产推荐使用 systemd)
seekcode daemon --all-installed > /var/log/seekcode.log 2>&1 &输出示例:
Multi-repo daemon started: round interval 300s
[multi-daemon] round start: 15 repos
[multi-daemon] your-org/api: 1 reviewed, 0 skipped, 0 failed
[multi-daemon] your-org/web: 0 reviewed, 1 skipped, 0 failed
...
[multi-daemon] round done: 15/15 succeeded, 3 PRs reviewed生产部署(systemd / Docker / 健康监控)见下方 生产部署 章节。
seekcode pr list
跨仓库浏览开放的 Pull Request,不调用 LLM、不发评论,只是一次轻量的 GraphQL 批量查询 + 本地状态查找。适合在跑 seekcode review 之前看一眼"现在有哪些 PR"。
# 单仓库
seekcode pr list --repo your-org/api
# 多仓库(逗号分隔)
seekcode pr list --repos your-org/api,your-org/web,your-org/worker
# 全部已安装 App 的仓库
seekcode pr list --all-installed
# 包含 draft (默认排除)
seekcode pr list --all-installed --include-drafts
# 只看最近 5 个 (按 updated_at 倒序)
seekcode pr list --all-installed --limit 5
# JSON 输出 — 给 jq / shell 脚本用
seekcode pr list --all-installed --json | jq '.[] | select(.reviewed == false)'输出示例:
REPO PR TITLE AUTHOR UPDATED
────────────── ──── ──────────────────────────── ────── ───────
🟢 org/api #123 Add password reset endpoint alice 3h
✅ org/web #45 Fix login redirect bob 2d
📝 org/api #124 WIP: refactor auth alice 5h
3 open PRs across 102 repos · 1 already reviewed by seekcode
Legend: 🟢 not reviewed ✅ reviewed at current sha 📝 draft状态图标含义:
| 图标 | 含义 | |---|---| | 🟢 | 未被 seekcode 在当前 head sha 上 review 过 — daemon 下一轮会处理 | | ✅ | 已经在当前 sha review 过 — daemon 会跳过 (幂等) | | 📝 | Draft PR — 默认不会被 daemon 处理 (除非 PR 被标记为 ready) |
✅ 标识用的是跟 daemon 相同的 state store key (projectPath + prNumber + sha),所以你看到的就是 daemon 实际会跳过的。
可选参数:
| 参数 | 说明 | 默认 |
|------|------|------|
| --repo <owner/repo> | 单仓库 | — |
| --repos <list> | 逗号分隔的仓库列表 | — |
| --all-installed | 自动发现所有安装了 canziAI App 的仓库 | — |
| --include-drafts | 是否包含 draft PR | false |
| --limit <n> | 最多显示多少条 (按 updated_at 倒序) | 全部 |
| --json | 输出 JSON 而不是表格 | false |
| --config <path> | 指定配置文件 | 自动发现 |
典型用法 — 给 daemon 配置仓库列表:
# 1. 看一眼自动发现的仓库都有哪些活动
seekcode pr list --all-installed --limit 20
# 2. 把活跃的几个明确写到 config (让 daemon 只跑你关心的)
cat >> ~/.seekcode/config.yml <<'EOF'
daemon:
repos:
- your-org/api
- your-org/web
EOFseekcode login / seekcode logout
GitHub OAuth 凭证管理。
seekcode login # 交互式 Device Flow 登录
seekcode logout # 删除 ~/.seekcode/auth.json登录流程:
Open: https://github.com/login/device
Enter code: ABCD-1234激活码可以在任意浏览器输入(运行 seekcode login 的机器自身不需要浏览器 — 配合 sudo -u 可在无头服务器使用)。
登录后 token 每 8 小时自动续期,refresh token 本身寿命为 6 个月。
配置文件
默认位置: ~/.seekcode/config.yml
自动发现顺序(不指定 --config 时):
- 当前目录或任意父目录中的
seekcode.yml、seekcode.yaml或.seekcoderc.yml,向上找到 git 仓库根 ~/.seekcode/config.yml~/.config/seekcode/config.yml
完整字段说明:
# GitHub 相关(主要给 GitHub Enterprise 用)
github:
baseUrl: https://api.github.com # GitHub Enterprise 改这里
# Daemon 设置(仅 `seekcode daemon` 使用)
daemon:
intervalSeconds: 300 # 两轮间隔
allInstalled: true # 自动发现已安装 App 的仓库
# repos: # 或显式列表(与 allInstalled 二选一)
# - your-org/api
# - your-org/web
maxParallelRepos: 2 # 单轮内并发仓库数
maxCostPerHourUsd: 10.00 # 滚动 1h 成本超限则跳过下轮(0 = 禁用)
# 审查设置
review:
postCommentByDefault: false # 设为 true 可省略 --post-comment
maxDiffChars: 100000 # 超过此 size 的 diff 会被截断
maxSoulChars: 2000 # 超过此 size 的 SOUL.md 会被截断
outputLanguage: en # en, zh-CN, zh-TW, ja, es, fr, de, pt-BR, ko
# LLM 设置
agent:
adapter: goatchain # v0.1 仅支持 goatchain
baseUrl: https://api.openai.com/v1
apiKey: sk-xxx # 注意保密
modelId: gpt-4o
costPerMillionTokensUsd: 5.00 # daemon 成本估算用;0 = 禁用估算项目级覆盖:
在你的代码仓库里放一个 seekcode.yml(必须在 git 仓库内),从该仓库子目录运行 seekcode review 时会自动发现。项目级配置优先于 ~/.seekcode/config.yml。
环境变量
所有环境变量都会覆盖配置文件中的同名字段。
认证
| 变量 | 作用 |
|------|------|
| GITHUB_TOKEN | 直接使用此 token,跳过 OAuth 文件和 gh CLI |
LLM endpoint
| 变量 | 作用 |
|------|------|
| SEEKCODE_MODEL_BASE_URL | 覆盖 agent.baseUrl |
| SEEKCODE_MODEL_API_KEY | 覆盖 agent.apiKey |
| SEEKCODE_MODEL_ID | 覆盖 agent.modelId |
输出
| 变量 | 作用 |
|------|------|
| SEEKCODE_OUTPUT_LANGUAGE | 覆盖 review.outputLanguage |
| SEEKCODE_VERBOSE=1 | 等同 --verbose |
审查调优(高级)
| 变量 | 默认 | 说明 |
|------|------|------|
| REVIEW_MAX_CHANGED_FILES | 150 | 超过该数量切换到 Large Review 模式 |
| REVIEW_MAX_REVIEW_FILES | 10 | Shallow Review 阶段最多审查的文件数 |
| REVIEW_MAX_DIFF_LINES_PER_FILE | 120 | 单文件 diff 行数截断阈值 |
| REVIEW_MAX_DEEP_FILES | 4 | Deep Dive 阶段最多审查的文件数 |
| REVIEW_MAX_EXTRA_READS | 10 | 单次 review 最多读取的额外文件片段数 |
| REVIEW_MAX_CONTEXT_LINES_PER_READ | 120 | 单次读取的最大行数 |
| REVIEW_MAX_SUGGESTIONS | 10 | 单次 review 最多发表的行级建议数 |
| REVIEW_MAX_TOKENS_PER_REVIEW | 200000 | 软上限;超过后告警但不中断 |
| REVIEW_MAX_POLICY_CHARS | 2000 | SOUL.md 最大注入字符数 |
| REVIEW_MAX_REFERENCE_READS | 6 | 语言指南最大加载次数 |
| REVIEW_MAX_REFERENCE_TOTAL_CHARS | 12000 | 单次 review 引用指南总字符上限 |
SOUL.md — 仓库级审查规则
在仓库根目录放一个 SOUL.md 文件,定义项目自己的审查准则:
# our-api 审查规则
## 必须遵守
- 所有公开 REST 接口必须有 OpenAPI 注解
- 数据库查询必须使用参数化语句(禁止字符串拼接)
- 新接口必须有 tests/api/ 下的集成测试
## 禁止
- 禁止硬编码凭证、token、URL
- 生产代码路径禁止 console.log
- 禁止超过 5 行的注释代码块
## 风格
- 函数名必须是动词短语
- 避免缩写,例外:`db`、`id`、`url`、`api`Seekcode 从当前 PR 的 head commit 加载它(每个 PR 都可以更新自己的规则),作为上下文喂给 AI reviewer。Reviewer 会引用这些规则来判断问题。
约束:
- 路径:必须在仓库根目录,文件名严格为
SOUL.md - 大小:超过
review.maxSoulChars(默认 2000)会截断 - 可选:没有
SOUL.md也能审查,只是没有项目级上下文
认证机制
Seekcode 使用 GitHub OAuth Device Flow — 不需要 client secret,可安全用作公开 CLI。
Token 解析顺序(首个匹配为准):
GITHUB_TOKEN环境变量seekcode login写入的 OAuth token(自动续期)gh auth token(如果安装了 GitHub CLI)
Token 存储:
- 文件:
~/.seekcode/auth.json(mode 0600) - 包含:access_token、refresh_token、过期时间戳
- 绝不要提交此文件
Token 寿命(GitHub 官方设定,不可修改):
| Token | 寿命 | |-------|------| | Access token | 8 小时 | | Refresh token | 6 个月 |
自动续期:
每次发起 GitHub API 请求前,seekcode 检查 access token。如果剩余不到 5 分钟,自动用 refresh token 换取新的一对 token,对调用方完全透明。长跑 daemon 可在 refresh token 整个 6 个月生命周期内无人值守运行。
Refresh token 过期处理:
seekcode status 会在过期前 14 天告警。真正过期后会显示 ✗ OAuth token expired,重新登录:
seekcode logout
seekcode login成本控制
LLM 成本按每次 review 估算 — token 总数 × agent.costPerMillionTokensUsd。成本记录到 ~/.seekcode/state/cost-log.jsonl。
两层控制:
单次 review token 上限 —
REVIEW_MAX_TOKENS_PER_REVIEW环境变量(默认 200000)。软上限:超过后告警但不中断。每小时支出上限(仅 daemon) —
daemon.maxCostPerHourUsd配置项。硬上限:滚动 1 小时成本超过该值时,下一轮被跳过。daemon 不会停止,下一轮窗口滑动后会重试。
生产推荐配置:
agent:
costPerMillionTokensUsd: 5.00 # 设为你的供应商实际单价(每 1M tokens)
daemon:
maxCostPerHourUsd: 20.00 # 硬上限查看当前消耗:
seekcode status
# 关注:Cost (last hour): $X.XX注意: 当前估算用单一费率算 prompt + completion 总和。对于 GPT-4o 等输入输出价格不同的模型($2.50 / $10),估算可能差 2-4 倍。建议用较高的 output 价格作为保守估算。
生产部署
下面是一份完全自包含的 systemd 部署配方(无需克隆源码仓库),从零到 daemon 上线 + 健康监控 + Slack 告警全流程,全部命令直接复制粘贴可用。
TL;DR 步骤:
# 1. 创建专用用户
sudo useradd -r -m -d /var/lib/seekcode -s /usr/sbin/nologin seekcode
sudo mkdir -p /var/lib/seekcode/.seekcode
sudo chown -R seekcode:seekcode /var/lib/seekcode
# 2. 全局安装
sudo npm install -g @archships/seekcode-cli
# 3. 登录(一次性,之后 6 个月免维护)
sudo -u seekcode -H seekcode login
# 4. 写配置
sudo -u seekcode tee /var/lib/seekcode/.seekcode/config.yml > /dev/null <<'EOF'
daemon:
intervalSeconds: 600
allInstalled: true
maxParallelRepos: 2
maxCostPerHourUsd: 10.00
review:
postCommentByDefault: true
outputLanguage: zh-CN
agent:
adapter: goatchain
baseUrl: https://api.openai.com/v1
apiKey: sk-xxx
modelId: gpt-4o
costPerMillionTokensUsd: 5.00
EOF
sudo chmod 600 /var/lib/seekcode/.seekcode/config.yml
# 5. 写入 systemd unit
sudo tee /etc/systemd/system/seekcode.service > /dev/null <<'EOF'
[Unit]
Description=Seekcode multi-repo PR review daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=seekcode
Group=seekcode
WorkingDirectory=/var/lib/seekcode
Environment="HOME=/var/lib/seekcode"
ExecStart=/usr/bin/seekcode daemon --all-installed --post-comment
Restart=on-failure
RestartSec=30s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=seekcode
# Resource limits
MemoryMax=1G
TasksMax=64
# Hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/seekcode
PrivateTmp=yes
PrivateDevices=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now seekcode
# 6. 验证
sudo systemctl status seekcode
sudo journalctl -u seekcode -f
sudo -u seekcode seekcode status健康监控
强烈推荐配合一个 systemd timer 每 5 分钟自检一次 daemon 状态,触发时通过 Slack-style webhook 告警。
步骤 1:写入健康检查脚本到 /usr/local/bin/seekcode-healthcheck.sh(点击展开完整脚本):
sudo tee /usr/local/bin/seekcode-healthcheck.sh > /dev/null <<'BASH'
#!/usr/bin/env bash
# Seekcode daemon health check
# Verifies the daemon is alive, the last round finished recently, and the
# cost is within budget. Exits non-zero on failure.
#
# Environment variables:
# SEEKCODE_USER - user to run seekcode as (default: seekcode)
# STALE_THRESHOLD_SEC - alert if last round older than this (default: 1800)
# COST_THRESHOLD_USD - alert if last-hour cost exceeds this (default: 0 = off)
# ALERT_WEBHOOK - optional Slack-style webhook URL
set -euo pipefail
SEEKCODE_USER="${SEEKCODE_USER:-seekcode}"
STALE_THRESHOLD_SEC="${STALE_THRESHOLD_SEC:-1800}"
COST_THRESHOLD_USD="${COST_THRESHOLD_USD:-0}"
ALERT_WEBHOOK="${ALERT_WEBHOOK:-}"
alert() {
local severity="$1"
local message="$2"
echo "[$severity] $message" >&2
if [[ -n "$ALERT_WEBHOOK" ]]; then
curl -fsS -X POST "$ALERT_WEBHOOK" \
-H 'Content-Type: application/json' \
-d "{\"text\":\"🚨 seekcode [$severity]: $message\"}" \
>/dev/null 2>&1 || true
fi
}
# 1. Service alive
if command -v systemctl >/dev/null 2>&1; then
if ! systemctl is-active --quiet seekcode.service; then
alert "CRITICAL" "seekcode.service is not active"
exit 1
fi
fi
# 2. Capture status
STATUS_OUTPUT=$(sudo -u "$SEEKCODE_USER" -H seekcode status 2>&1) || {
alert "CRITICAL" "seekcode status failed: $STATUS_OUTPUT"
exit 4
}
# 3. Auth check
if echo "$STATUS_OUTPUT" | grep -q '✗ Not authenticated\|✗ OAuth token expired'; then
alert "CRITICAL" "seekcode is not authenticated — run 'seekcode login'"
exit 4
fi
# 3.5 Refresh token expiry warning (< 14 days)
if echo "$STATUS_OUTPUT" | grep -q 'Refresh token expires in'; then
REFRESH_LINE=$(echo "$STATUS_OUTPUT" | grep 'Refresh token expires in' | head -1)
alert "WARNING" "$REFRESH_LINE"
fi
# 4. Last round freshness
FINISHED_LINE=$(echo "$STATUS_OUTPUT" | grep -E '^\s*Finished:' | head -1 || true)
if [[ -z "$FINISHED_LINE" ]]; then
alert "WARNING" "no daemon round recorded yet"
exit 0
fi
FINISHED_TS=$(echo "$FINISHED_LINE" | awk '{print $2}')
if date -u -d "$FINISHED_TS" +%s >/dev/null 2>&1; then
LAST_EPOCH=$(date -u -d "$FINISHED_TS" +%s)
else
LAST_EPOCH=$(date -u -j -f "%Y-%m-%dT%H:%M:%S" "${FINISHED_TS%.*}" +%s 2>/dev/null || echo 0)
fi
NOW_EPOCH=$(date -u +%s)
DELTA=$((NOW_EPOCH - LAST_EPOCH))
if [[ "$DELTA" -gt "$STALE_THRESHOLD_SEC" ]]; then
alert "WARNING" "last daemon round was ${DELTA}s ago (threshold: ${STALE_THRESHOLD_SEC}s)"
exit 2
fi
# 5. Cost check
if [[ "$COST_THRESHOLD_USD" != "0" ]]; then
COST_LINE=$(echo "$STATUS_OUTPUT" | grep -E 'Cost \(last hour\)' || true)
if [[ -n "$COST_LINE" ]]; then
COST=$(echo "$COST_LINE" | grep -oE '\$[0-9]+\.[0-9]+' | tr -d '$' || echo "0")
OVER=$(awk -v c="$COST" -v t="$COST_THRESHOLD_USD" 'BEGIN { print (c > t) ? 1 : 0 }')
if [[ "$OVER" == "1" ]]; then
alert "WARNING" "hourly cost \$$COST exceeds threshold \$$COST_THRESHOLD_USD"
exit 3
fi
fi
fi
echo "OK: seekcode healthy (last round ${DELTA}s ago)"
exit 0
BASH
sudo chmod +x /usr/local/bin/seekcode-healthcheck.sh步骤 2:写入 healthcheck systemd service:
sudo tee /etc/systemd/system/seekcode-healthcheck.service > /dev/null <<'EOF'
[Unit]
Description=Seekcode daemon health check
After=seekcode.service
[Service]
Type=oneshot
User=root
Environment="STALE_THRESHOLD_SEC=1800"
Environment="COST_THRESHOLD_USD=15.00"
# 启用 Slack/webhook 告警:
# Environment="ALERT_WEBHOOK=https://hooks.slack.com/services/XXX/YYY/ZZZ"
ExecStart=/usr/local/bin/seekcode-healthcheck.sh
StandardOutput=journal
StandardError=journal
SyslogIdentifier=seekcode-healthcheck
EOF步骤 3:写入 timer(每 5 分钟触发):
sudo tee /etc/systemd/system/seekcode-healthcheck.timer > /dev/null <<'EOF'
[Unit]
Description=Run seekcode health check every 5 minutes
Requires=seekcode-healthcheck.service
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
AccuracySec=30s
[Install]
WantedBy=timers.target
EOF步骤 4:启用 timer:
sudo systemctl daemon-reload
sudo systemctl enable --now seekcode-healthcheck.timer
# 查看下次触发时间
sudo systemctl list-timers seekcode-healthcheck.timer
# 手动跑一次验证
sudo systemctl start seekcode-healthcheck.service
sudo journalctl -u seekcode-healthcheck.service -n 20告警触发条件:
- daemon 停止运行 (
CRITICAL) - 鉴权失效 (
CRITICAL) - 上一轮过老 (
WARNING,超过STALE_THRESHOLD_SEC) - 1 小时成本超阈值 (
WARNING,超过COST_THRESHOLD_USD) - Refresh token 不到 14 天就过期 (
WARNING)
Docker 部署
适合本机或 K8s / Docker Swarm。先在宿主机 seekcode init 完成认证,容器通过挂载 ~/.seekcode 复用同一份 config + auth + state。
任意空目录创建两个文件:
Dockerfile:
FROM node:20-alpine
ARG SEEKCODE_VERSION=latest
RUN npm install -g @archships/seekcode-cli@${SEEKCODE_VERSION} \
&& npm cache clean --force
USER node
WORKDIR /home/node
CMD ["seekcode", "daemon", "--all-installed", "--post-comment"]docker-compose.yml:
services:
seekcode-daemon:
build: .
image: seekcode-cli:local
container_name: seekcode-daemon
restart: unless-stopped
volumes:
- ${HOME}/.seekcode:/home/node/.seekcode
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"启动:
docker compose up -d --build # 构建 + 启动
docker compose logs -f seekcode-daemon # 查看日志
docker compose exec seekcode-daemon seekcode status # 容器内 status
docker compose down # 停止容器内 token 自动 refresh,新 token 通过 volume 写回宿主机。macOS Docker Desktop 需要在 Settings → Resources → File Sharing 允许 ~/.seekcode。锁定版本:docker compose build --build-arg SEEKCODE_VERSION=0.1.2。
故障排查
| 现象 | 解决方案 |
|------|---------|
| Not authenticated / OAuth token expired | seekcode logout && seekcode login |
| PR not found (404) | 仓库未安装 GitHub App。seekcode status 检查 installation 列表,必要时访问 https://github.com/apps/canziai/installations/new 安装 |
| LLM endpoint check failed — HTTP 401 | API key 不对 |
| LLM endpoint check failed — HTTP 404 | base URL 不对(缺 /v1 后缀?) |
| LLM endpoint check failed — timeout / ENOTFOUND | 网络 / DNS 问题 |
| No agent configuration found | 跑 seekcode init 重新配置 |
| Review 卡在 "ShallowReviewer Starting" | LLM 太慢或在限流。换更快模型 / 设 REVIEW_MAX_REVIEW_FILES=5 |
| ⏭️ skipped: Already reviewed for this SHA | 幂等保护。删 ~/.seekcode/state/reviews/<key>.json 或推新 commit |
| Daemon round 出现 partial / failed | sudo journalctl -u seekcode --since "1 hour ago" \| grep -i error |
| 想看完整异常栈 | 加 --verbose 或设 SEEKCODE_VERBOSE=1 |
常见问题
Q:会审查 PR 的每个 commit 还是只审查最新的?
A:只审查最新 commit(head_sha)。当 PR 收到新 commit 时,新 SHA 不在状态存储里,会自动重新审查。
Q:可以用本地 LLM(Ollama、llama.cpp)吗?
A:可以,只要它兼容 OpenAI Chat Completions API。把 agent.baseUrl 设为本地地址(例如 http://localhost:11434/v1),apiKey 随便填一个字符串即可。
Q:GitHub App 需要哪些权限? A:Pull requests(读写)、Contents(读)、Metadata(读)。安装 App 时会自动请求这些权限。
Q:API key 存在哪?
A:~/.seekcode/config.yml,明文,mode 0600。请像保护其他密钥一样保护这个文件。
Q:可以在多台机器上跑 daemon 吗?
A:可以,但注意:状态文件是机器本地的。如果两台 daemon 审查同一仓库会各自维护独立状态,可能重复 review(重复评论)同一个 PR。多机使用 daemon.allInstalled 时要谨慎。
Q:怎么查看 daemon 历史活动?
A:seekcode status 显示最近一轮统计。历史记录看 daemon 日志(systemd 用 journalctl -u seekcode)和成本日志(~/.seekcode/state/cost-log.jsonl)。
Q:怎么升级 seekcode?
A:npm update -g @archships/seekcode-cli 或 npm install -g @archships/seekcode-cli@latest。
Q:可以审查私有仓库吗? A:可以,前提是 GitHub App 已安装到该仓库,并且当前认证有权访问。
Q:可以自定义审查的 prompt 吗?
A:v0.1 不支持通过配置自定义。最接近的方式是 SOUL.md — 把项目级规则提交到仓库根目录,会被注入到审查上下文。可以用它来引导 reviewer 关注的重点。
Q:AI 能审查哪些编程语言? A:LLM 能理解的任何语言 — TypeScript、JavaScript、Python、Go、Rust、Java、C、C++、Vue/React 模板、CSS 等。内置语言指南覆盖:typescript、react、vue、rust、python、java、go、c、cpp、css-less-sass。
