Create a PR for the current branch (targets `canary` by default), including splitting one cross-layer branch into ordered stacked PRs so a lower layer (db / sha
复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-pr-27b8e6f65c13 ,按照其中的说明把「pr」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
canary (development branch, cloud production)main is the release branch — never PR directly to maingit branch --show-current — current branch namegit status --short — uncommitted changesgit rev-parse --abbrev-ref @{u} 2>/dev/null — remote tracking statusgit log --oneline origin/canary..HEAD — unpushed commitsgh pr list --head "$(git branch --show-current)" --json number,title,state,url — existing PRgit diff --stat --stat-count=20 origin/canary..HEAD — change summarypublish_lh acceptance run list --json and match on branch. Do not blindly unset API keys: the production credential may exist only in the environment. A lookup never requires creating a new round.If current branch is canary (or main) AND there are uncommitted changes:
git diff) to understand the changes<type>/<short-description> (e.g. fix/i18n-cjk-spacing)git checkout -b <branch-name>git add <files> (prefer explicit file paths over git add .)If current branch is canary/main but there are NO uncommitted changes and no unpushed commits, abort — nothing to create a PR for.
git push -u origin $(git branch --show-current)git push origin $(git branch --show-current)gh issue list --search "<keywords>" --state all --limit 10A feature or fix needs a published acceptance round before the PR is opened (AGENTS.md → Acceptance). If step 1 found none for this branch, run the acceptance skill first and come back with its https://app.lobehub.com/acceptance/<id> link. When the delivery was already verified on the real product earlier in the session, that skill's ingest path publishes the existing observations and artifacts directly — no re-run, no re-plan. Pure refactors or tooling changes with no user-visible outcome may skip it — state that in the PR body instead of leaving the line out.
gh pr create --base canary<gitmoji> <type>(<scope>): <description>.github/PULL_REQUEST_TEMPLATE.md)AGENT-INSTRUCTIONS HTML comments in that template. Keep them commented out, and do not copy them into the visible description.Fixes #123, Closes #123)Fixes LOBE-xxx)--body-file to preserve formatting.gh pr view --web
Use .github/PULL_REQUEST_TEMPLATE.md as the source of truth for body structure, contribution classification, disclosure eligibility, and required fields. Follow its AGENT-INSTRUCTIONS when filling these sections:
AI-assisted even when organization membership exempts the author from disclosing details; human review does not make it human-only. Use Unknown when the source cannot be established.Prompts and transcripts are private by default and are not required fields. Only if the author explicitly requests sharing them, review the exact proposed text for sensitive information and obtain confirmation before publishing that text. Authorization to create or update a PR is not consent to publish a conversation. Check attached logs and screenshots for sensitive information too.
The steps above create one PR for the current branch. When a single branch lands across layers — packages/database schema/model → a shared packages/* lib → src/server TRPC → apps/desktop + apps/cli callers → src/features UI — shipping it as one PR can't merge safely: the clients call an endpoint that doesn't exist on the trunk until the same PR merges, so any partial/rollback or independent review breaks. Split it into ordered PRs, lower layer first.
A PR may only merge after every layer it calls is already on the trunk.
canary right now, would it build and behave?" If no, it belongs in a later PR.The non-obvious calls:
listDevices now returns platform: string | null), the component consuming it must change in the same PR — otherwise the server PR breaks the build on its own. Contract + its in-repo consumers ship together.@lobechat/* package imported only by desktop/CLI ships in the client PR. Don't carry an unused package in the lower PR.package.json workspace:*, pnpm-workspace.yaml) travel with the code that imports the package.Starting point: one branch (feat/x) with a single commit <FULL> containing everything, already pushed (so it's also safe on the remote).
# 1. Safety nets — make the full work unloseable before rewriting anything
git branch backup/x-full <FULL> # local ref to the full commit
git branch feat/x-clients <FULL> # the higher-layer branch starts here
# 2. Rewrite the lower-layer branch to lower-layer files only
git checkout feat/x # this becomes the SERVER PR
git reset --hard origin/canary
git checkout <FULL> -- <server/db files…> # stages just those paths
git commit -m "✨ feat(...): <server half>"
git push --force-with-lease origin feat/x # never --force; never push to canary
# 3. Build the higher-layer branch STACKED on the lower branch
git checkout feat/x-clients
git reset --hard feat/x # base = the just-rewritten server HEAD
git checkout backup/x-full -- <client/ui files…> # only the remaining paths
git commit -m "✨ feat(...): <client half>"
git push -u origin feat/x-clients
Then open the higher PR based on the lower branch, not the trunk:
gh pr create --base feat/x --head feat/x-clients --title "…" --body "…"
--base feat/x keeps the diff client-only (no server files leak in) and makes it physically impossible to merge the clients before the server. After the server PR merges to canary, retarget the client PR's base to canary (GitHub usually auto-retargets when the base branch merges; note it in the PR body so a human confirms).
The whole point is the higher layer needs the lower one. Prove it: on the stacked higher branch, type-check the caller and confirm the symbol the lower layer introduced resolves.
cd apps/cli && bun run type-check 2>&1 | grep -iE "connect\.ts|device\.register"
# empty (re: your change) = the stacked base supplies device.register ✓
Filter to your touched files — this repo's standalone type-check emits pre-existing env noise (__ELECTRON__, @/types/llm, unbuilt @lobechat/types) that isn't yours.
Closes LOBE-<server>. Client PR: Closes LOBE-<pkg> / <desktop> / <cli>. Don't let one PR's body claim another layer's issue.Part of LOBE-<parent>.linear skill.canary. A split branch cut with git checkout -b feat/x origin/canary tracks origin/canary, so a bare git push targets canary. Always git push origin feat/x with the explicit branch name.--force-with-lease, not --force when rewriting the lower branch — it aborts if the remote moved under you.reset --hard. Step 1's backup/x-full + the pushed remote branch mean the full commit is referenced by ≥3 refs before you rewrite anything. Verify with git branch --contains <FULL>.pnpm-lock.yaml, so a new workspace:* dep needs no lockfile churn. In a repo that does commit one, regenerate it on each branch after the split.