npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

npm version weekly downloads total downloads

AI 驱动的 GitHub PR 自动 review CLI。多阶段流水线分析每个 Pull Request,将结构化报告回写到 GitHub,可单次运行也可作为长跑 daemon。


目录


功能简介

Seekcode 自动审查 GitHub Pull Request。每次运行会:

  1. 拉取 PR diff 和元数据
  2. 执行本地规则检查 — 密钥检测、超大 diff、生成文件识别
  3. 加载 SOUL.md(如果存在)— 仓库自定义的审查准则
  4. 运行 5 阶段 LLM 审查流水线
    • Preflight — 文件评分,挑选优先级高的候选
    • Shallow Review(>150 文件时切到 Large Review)— 浅层快速发现高价值问题
    • Deep Dive(可选)— 对高风险文件深入分析
    • Test Planning — 测试建议
    • Description Summary — 简短摘要
  5. 将结构化报告回帖到 PR(重复审查时 upsert)
  6. 可选行级建议 — 用 suggestion 代码块发送内联建议
  7. 状态去重 — 同一 commit 不会重复审查

兼容任何 OpenAI 兼容的 LLM endpoint(OpenAI、Azure、GLM、DeepSeek、本地 Ollama 等)。

支持 9 种输出语言enzh-CNzh-TWjaesfrdept-BRko


安装

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-comment

init 向导会引导你完成:

  1. GitHub OAuth 登录(Device Flow)— 浏览器输入 8 位激活码即可
  2. 安装 GitHub App 到你想 review 的仓库(自动打开安装页)
  3. 配置 LLM endpoint — base URL、API key、模型 ID
  4. 选择输出语言 — 默认英文

配置写入 ~/.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 不可达 | 检查 baseUrlapiKey、网络 | | ⚠️ 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> | 覆盖输出语言(enzh-CNja 等) | 来自 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.reposdaemon.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
EOF

seekcode 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 时):

  1. 当前目录或任意父目录中的 seekcode.ymlseekcode.yaml.seekcoderc.yml,向上找到 git 仓库根
  2. ~/.seekcode/config.yml
  3. ~/.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 解析顺序(首个匹配为准):

  1. GITHUB_TOKEN 环境变量
  2. seekcode login 写入的 OAuth token(自动续期)
  3. 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

两层控制:

  1. 单次 review token 上限REVIEW_MAX_TOKENS_PER_REVIEW 环境变量(默认 200000)。软上限:超过后告警但不中断。

  2. 每小时支出上限(仅 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-clinpm 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。