boring-new-app

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Set up a new app repository, end to end

端到端设置新的 app repository

You act for the maintainer (the person who owns the Factory). The result is a repository where the expert's agent can start a feature and the Factory takes it from there. Do every step yourself; ask the person only for the decisions below and for what needs their browser.
你代表 maintainer(Factory 的所有者)执行操作。最终应得到一个 repository,使 expert 的 agent 可以在其中启动一个 feature,之后由 Factory 接手。所有步骤都要自行完成;仅针对以下决策以及必须由其浏览器处理的事项向对方询问。

0. Decide with the person (one message, all at once)

0. 与对方共同确定(一条消息中一次性确认)

  • Repository:
    OWNER/NAME
    (new) — or an existing repository (then go to §6).
  • Title of the app.
  • Runtime:
    vm
    (a container on a host you own; agents run in the app) or
    cloudflare
    (a Worker with D1; its agents are declarative and run by the hub, no agent with code, no job). Default
    vm
    .
  • Expert: their GitHub login. It must not be the bot's account (GitHub forbids approving your own pull request, and the bot opens contract PRs).
  • Bot: the account whose token is
    FACTORY_TOKEN
    (default: the maintainer).
  • Repository:
    OWNER/NAME
    (新建)——或使用现有 repository(此时转到 §6)。
  • Title:app 的标题。
  • Runtime:
    vm
    (位于自有 host 上的 container;agents 在 app 中运行),或
    cloudflare
    (使用 D1 的 Worker;其 agents 为 declarative,由 hub 运行,不含带代码的 agent,也没有 job)。默认值为
    vm
    。
  • Expert:其 GitHub login。不得使用 bot 的 account(GitHub 禁止 approve 自己的 pull request,而 bot 会开启 contract PR)。
  • Bot:token 为
    FACTORY_TOKEN
    的 account(默认为 maintainer)。

1. Preconditions (check, fix what you can)

1. 前置条件(检查并尽可能修复问题)

bash
gh auth status                       # signed in as the maintainer, scopes repo + workflow
gh auth setup-git                    # git (and npx github:…) use gh's credentials
gh api repos/hachej/boring-factory --jq .full_name    # read access to the factory
gh api repos/hachej/boring-app --jq .is_template      # the app template: must print true
gh api repos/hachej/boring-factory/actions/permissions/access --jq .access_level   # must be "user"
If the access level is not
user
, other repositories cannot call the factory's workflows:
gh api -X PUT repos/hachej/boring-factory/actions/permissions/access -f access_level=user
.
Ask the person to confirm once (cannot be checked with a token):
bash
gh auth status                       # signed in as the maintainer, scopes repo + workflow
gh auth setup-git                    # git (and npx github:…) use gh's credentials
gh api repos/hachej/boring-factory --jq .full_name    # read access to the factory
gh api repos/hachej/boring-app --jq .is_template      # the app template: must print true
gh api repos/hachej/boring-factory/actions/permissions/access --jq .access_level   # must be "user"
如果 access level 不是
user
,其他 repository 就无法调用 Factory 的 workflows:
gh api -X PUT repos/hachej/boring-factory/actions/permissions/access -f access_level=user
。
请对方一次性确认以下事项(无法通过 token 检查):

2. The three secrets

2. 三个 secrets

Never print a secret; pipe it into
gh secret set
.
SecretWhere it comes from
FACTORY_TOKEN
The bot's token. When the bot is the signed-in maintainer:
gh auth token
CURSOR_API_KEY
The maintainer's Cursor key (from your secret store)
CLAUDE_CODE_OAUTH_TOKEN
Only the person:
claude setup-token
on their machine (Claude Pro/Max). Never ask them to paste it into the chat: they run
gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo OWNER/NAME
themselves, or export it before §3
Export what you can before §3 so that
init
sets them:
bash
export FACTORY_TOKEN="$(gh auth token)"
export CURSOR_API_KEY="…"            # read from your secret store, never echoed
绝不要打印 secret;应通过管道将其传给
gh secret set
。
Secret来源
FACTORY_TOKEN
bot 的 token。当 bot 是已登录的 maintainer 时:
gh auth token
CURSOR_API_KEY
maintainer 的 Cursor key(来自你的 secret store)
CLAUDE_CODE_OAUTH_TOKEN
只能由本人获取:在其机器上运行
claude setup-token
(Claude Pro/Max)。绝不要要求对方粘贴到聊天中:让对方自行运行
gh secret set CLAUDE_CODE_OAUTH_TOKEN --repo OWNER/NAME
,或在 §3 之前将其 export
在 §3 之前 export 可获取的变量,以便
init
设置它们:
bash
export FACTORY_TOKEN="$(gh auth token)"
export CURSOR_API_KEY="…"            # read from your secret store, never echoed

3. Create the repository

3. 创建 repository

Dry run first, read the plan back to the person in three lines, then create:
bash
npx -y github:hachej/boring-factory init OWNER/NAME --expert EXPERT --bot BOT --title "TITLE" --runtime vm
npx -y github:hachej/boring-factory init OWNER/NAME --expert EXPERT --bot BOT --title "TITLE" --runtime vm --yes
init
creates the private repository from the template hachej/boring-app (
gh repo create --template
), pushes one commit that makes it this app (name, title, port, runtime:
scripts/init-app.mjs
keeps only
deploy/<runtime>/
; CODEOWNERS; the expert in
project.md
), applies the labels and settings, invites the expert, sets the secrets found in the environment and the
FACTORY_BOT
variable. Then set any secret it reports missing (§2). The app carries no skills and pins nothing: its workflows call boring-factory at
@main
.
Production is set up later, by hand, from
deploy/<runtime>/DEPLOY.md
in the app;
init
prints the commands. On Cloudflare the production token lives only in the GitHub environment
production
(restricted to
main
), never as a repository secret, and previews use a separate account's token.
先执行 dry run,用三行向对方复述计划,然后再创建:
bash
npx -y github:hachej/boring-factory init OWNER/NAME --expert EXPERT --bot BOT --title "TITLE" --runtime vm
npx -y github:hachej/boring-factory init OWNER/NAME --expert EXPERT --bot BOT --title "TITLE" --runtime vm --yes
init
会从 template
hachej/boring-app
创建 private repository(
gh repo create --template
),推送一次 commit,使它成为当前 app(name、title、port、runtime;
scripts/init-app.mjs
仅保留
deploy/<runtime>/
;CODEOWNERS;在
project.md
中加入 expert),应用 labels 和 settings,邀请 expert,设置在 environment 中找到的 secrets 以及
FACTORY_BOT
variable。然后设置它报告缺失的所有 secret(§2)。该 app 不包含任何 skill,也不 pin 任何版本:其 workflows 以
@main
调用 boring-factory。
Production 稍后根据 app 中的
deploy/<runtime>/DEPLOY.md
手动设置;
init
会打印相关命令。在 Cloudflare 上,production token 只存放在 GitHub environment
production
中(限制为
main
),绝不作为 repository secret;previews 使用另一个 account 的 token。

4. Verify, do not assume

4. 进行验证,不要想当然

bash
gh secret list --repo OWNER/NAME                     # the three names
gh variable list --repo OWNER/NAME                   # FACTORY_BOT
gh label list --repo OWNER/NAME --limit 100 | wc -l  # 26 or more
gh api repos/OWNER/NAME/invitations --jq '.[].invitee.login'
gh run list --repo OWNER/NAME --limit 5
The first
ci
run on
main
:
  • paths
    is red, expected: the customising commit was pushed straight to
    main
    .
  • check
    must be green. If it is red, read
    gh run view <id> --log-failed
    , fix the cause in the template, hachej/boring-app, first (it will hit every new app), then in the app through a pull request.
bash
gh secret list --repo OWNER/NAME                     # the three names
gh variable list --repo OWNER/NAME                   # FACTORY_BOT
gh label list --repo OWNER/NAME --limit 100 | wc -l  # 26 or more
gh api repos/OWNER/NAME/invitations --jq '.[].invitee.login'
gh run list --repo OWNER/NAME --limit 5
main
上的首次
ci
run:
  • paths
    为 红色,且符合预期:用于定制的 commit 被直接推送到了
    main
    。
  • check
    必须为 绿色。如果为红色,读取
    gh run view <id> --log-failed
    ,先在 template
    hachej/boring-app
    中修复原因(该问题会波及每个新 app),再通过 pull request 修复 app 中的问题。

5. Hand over to the expert

5. 向 expert 交接

Send the person this, filled in:
Accept the invitation to OWNER/NAME, then on your machine:
npx skills add hachej/boring-stack --skill boring-pm -g
and
gh repo clone OWNER/NAME
, open your agent (Claude Code, Codex or Cursor) inside the clone and describe what you want.
Tell the maintainer what to watch: the factory workflow in the Actions tab (
context → ci → triage → checks → gates → build
), triage's one comment per event, and the checks
boring/ci
and
boring/proof
on each pull request.
向对方发送以下内容,并填入相应信息:
接受 OWNER/NAME 的邀请,然后在自己的机器上:
npx skills add hachej/boring-stack --skill boring-pm -g
和
gh repo clone OWNER/NAME
,在 clone 目录中打开你的 agent(Claude Code、Codex 或 Cursor)并描述你的需求。
告诉 maintainer 应关注什么:Actions tab 中的 factory workflow(
context → ci → triage → checks → gates → build
)、triage 针对每个 event 留下的一条 comment,以及每个 pull request 上的
boring/ci
和
boring/proof
checks。

6. An existing repository instead

6. 使用现有 repository

bash
npx -y github:hachej/boring-factory sync OWNER/NAME --dry-run
npx -y github:hachej/boring-factory sync OWNER/NAME --yes     # labels + the "Adopt the Boring Factory" pull request
The pull request adds only the files the repository lacks, copied from the template (the
factory.yml
caller, forms, PR template, CODEOWNERS, the ask rules,
project.md
). Fill
setup
and
check
in
project.md
on its branch, merge it by hand once (the Factory is not active before it lands), then §2, §4, §5. It is a one-shot adoption: nothing is tracked or bumped afterwards.
bash
npx -y github:hachej/boring-factory sync OWNER/NAME --dry-run
npx -y github:hachej/boring-factory sync OWNER/NAME --yes     # labels + the "Adopt the Boring Factory" pull request
该 pull request 只会添加 repository 中缺少的文件,这些文件从 template 复制而来(
factory.yml
caller、forms、PR template、CODEOWNERS、ask rules、
project.md
)。在其 branch 上填写
project.md
中的
setup
和
check
,手动 merge 一次(在合并落地前 Factory 不会激活),然后执行 §2、§4、§5。这是一次性 adoption:之后不会跟踪任何内容,也不会进行版本升级。

When something fails

出问题时

SymptomCauseFix
factory / context
fails with
gh api …: Not Found (404)
A factory bug or a token without accessRead the exact path in the log; if the token is fine, fix it in boring-factory's main (apps call it at
@main
)
A job says it cannot use
hachej/boring-factory/.github/workflows/…
The factory's workflows are not shared§1, access level
user
check
red on a fresh app
A template bugFix it in hachej/boring-app, then in the app
check
refuses an agent on a Cloudflare app
An agent or chat with
index.mjs
, a job, or Node in server code
Make the agent declarative, or choose
runtime: vm
Triage or the claude worker never runs
CLAUDE_CODE_OAUTH_TOKEN
missing or expired
§2
The expert cannot approve the contract PRThe expert is the bot's accountUse another account for the expert
A Cursor task fails at onceCursor quota or GitHub integrationEnable on-demand usage; connect the repo; or label the task
builder:claude
npx github:hachej/boring-factory
cannot fetch
git has no credentials
gh auth setup-git
Fix the cause in boring-factory (the process) or hachej/boring-app (the template) when it is theirs, so the next app does not hit it; never patch only the app.
症状原因修复
factory / context
因
gh api …: Not Found (404)
而失败
Factory bug,或 token 没有访问权限读取 log 中的确切路径;如果 token 没问题,则在 boring-factory 的 main 中修复(apps 以
@main
调用它)
Job 表示无法使用
hachej/boring-factory/.github/workflows/…
Factory 的 workflows 未被共享§1,access level
user
新 app 上的
check
为红色
Template bug先在
hachej/boring-app
中修复,再在 app 中修复
Cloudflare app 上的
check
拒绝某个 agent
Agent 或 chat 包含
index.mjs
、包含 job,或 server code 中使用了 Node
将 agent 改为 declarative,或选择
runtime: vm
Triage 或 claude worker 一直不运行
CLAUDE_CODE_OAUTH_TOKEN
缺失或过期
§2
Expert 无法 approve contract PRExpert 是 bot 的 account为 expert 使用另一个 account
Cursor task 立即失败Cursor quota 或 GitHub integration启用 on-demand usage;连接 repo;或将 task 标记为
builder:claude
npx github:hachej/boring-factory
无法 fetch
Git 没有 credentials
gh auth setup-git
如果原因属于 boring-factory(process)或 hachej/boring-app(template),就在相应位置修复,让下一个 app 不会再次遇到该问题;绝不要只 patch app。