sync-upstream
Skill149 starsChanged 7 days agoApache-2.0View on GitHub
Sync the Switchboard client with a newer official LibreChat server version — a stable release, a release candidate, or a PARTIAL sync up to an untagged upstream commit (e.g. current dev HEAD). If the client is ALREADY at the target commit, runs an AUDIT of the last synced delta to catch anything that was missed. Coordinates two dynamic workflows (discovery, implementation) around human decision gates.
- Commits and pushes
15 other projects use a version of this.
Adopted by
Most recently taken up by
- next-step/nextstep-skillstheir own version, first seen Nov 8, 2026
- parkchu/nextstep-claude-skillstheir own version, first seen Nov 1, 2026
- parkchu/nextstep-skillstheir own version, first seen Oct 17, 2026
- microsoft/vscodetheir own version, first seen Oct 13, 2026
- madeordinary/serel-memorytheir own version, first seen Oct 9, 2026
- lucasheriques/pstacktheir own version, first seen Oct 9, 2026
Used with
Projects with it also use start-mission, tdd and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
parkchuSkillstart-mission
넥스트스텝(NextStep) 미션을 처음 시작할 때, 미션 저장소를 fork·clone하고 최초 작업 브랜치(step1 등)까지 만들어 준다. gh CLI로 fork하고 clone까지 이어서 처리하며, gh가 없거나 인증이 안 돼 있으면 브라우저 Fork 안내로 폴백한다. 이미 fork/clone돼 있으면 재사용하고 이어서 진행한다(재실행 안전). 사용자가 "미션 시작하려는데 저장소 세팅해줘", "새 미션 시작할래", "fork부터 해줘", "/nextstep:start-mission" 등으로 요청할 때 사용한다.
Also in 3 projects that use this
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 3 projects that use this
MicrosoftSkillhandoff
Compact the current conversation into a handoff document for another agent to pick up.
Also in 3 projects that use this
Other versions15 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 15
- microsoft/vscode★ 195ksame name
- nyaruka/phonenumbers★ 1.6ksame name
- nklisch/claude-code-modes★ 116same name
- ric03uec/clawrium★ 67same name
- leandrocfe/skills★ 31same name
- tigercosmos/code-cortex-mcp★ 12same name
- freskhu/genesis★ 5same name
- lucasheriques/pstack★ 3same name
- toverux/cantrips★ 3same name
- madeordinary/serel-memory★ 1same name
5 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository13 other files it gives its agents.
- app/CLAUDE.mdCLAUDE.md
- build-logic/CLAUDE.mdCLAUDE.md
- CLAUDE.mdCLAUDE.md
- fastlane/CLAUDE.mdCLAUDE.md
- .github/CLAUDE.mdCLAUDE.md
- shared/CLAUDE.mdCLAUDE.md
- audit-depsSkill
- audit-i18nSkill
- audit-paritySkill
- marketing-refreshSkill
- release-highlightsSkill
- small-screensSkill
- update-web-assetsSkill
The file
We split this skill into the rules it gives an agent
5 rules. 0 are common, 1 is distinctive, and 4 are very specific to this project.
0
Common
Most of the 11 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 76
Always: submodule HEAD must equal commit=.
- Very specific: line 86
Detect mode: If {target_commit} == commit= (submodule HEAD) or $ARGUMENTS contains audit → audit mode.
- Distinctive: line 89
If sync mode and no newer tags AND branch heads == base → tell the user "already up to date" and offer an audit instead of stopping.
- Very specific: line 136
If a prior run's artifacts exist (ls .claude/sync-upstream/artifacts/), offer to resume from them.
- Very specific: line 218
If buildGreen is false or unresolvedConfirmed is true, report it and route back into WF2 (scoped to the failures) rather than proceeding.
“Common” is measured: kept by at least 6 in 10 of the 11 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Sync Upstream
Synchronize the Switchboard app with a newer version of the official LibreChat server.
You are the coordinator. You run the lightweight deterministic work yourself with Bash
(prereqs, target/mode resolution, final consistency asserts) and own the three human decision
points. All heavy parallel work is delegated to two dynamic workflows — you never read or
write app code yourself.
[you] 0. Prereqs + resolve target + detect mode (Bash — fail loud on ambiguity)
│
[WF1] 1. sync-upstream-discovery — parallel multi-angle sweep → converged findings
│
[you] 2. HITL INTERVIEW — the one real gate: target + scope + direction (AskUserQuestion)
│
[WF2] 3. sync-upstream-implement — implement → build+consistency gates → ≥2 independent review passes
│
[you] 4. TEST + PUSH TAIL — present test plan, facilitate device testing, hold the push gateTwo workflows do the work; you hold the seams. A workflow cannot pause to ask the user — that is exactly why the target choice, the proposal approval, and the no-push/device-test boundary live in your main loop between invocations, never inside a script.
Two modes
Resolve these before anything else (Phase 0), because they change the whole run:
| Mode | Trigger | Goal | Version bookkeeping |
| sync | resolved target commit ≠ current pin | absorb new upstream changes | advances (version.properties, UPSTREAM_VERSION, submodule, commit map) |
| audit | resolved target commit == current pin (or audit in $ARGUMENTS) | re-check that the LAST synced delta was fully/correctly absorbed — find misses | none — the pin does not move |
Audit's default range is the last synced delta (previous pin → current pin), recovered from
UPSTREAM_VERSION's own git history. --full widens it to full-pin reconciliation.
Target Modes (sync)
| Mode | Target looks like | backendTargetVersion | UPSTREAM_VERSION | Gating strategy |
| release | v0.8.8 (default: latest stable tag) | 0.8.8 | tag=v0.8.8, commit=<tag commit> | isCompatibleOrNewer(version, "0.8.8-rc1") |
| rc | v0.8.8-rc1 | 0.8.8-rc1 | tag=v0.8.8-rc1, commit=<tag commit> | isCompatibleOrNewer(version, "0.8.8-rc1") |
| partial | dev, main, or a SHA | <base>+dev.<sha8> | tag=<last v-tag at/before commit>, commit=<target SHA> | supportsFeature(detected, "<next-rc-line>", landedDate) |
Shared invariants: the diff base is always commit= from UPSTREAM_VERSION (never tag=);
BackendVersion.parse() handles all three forms; a later sync from a partial baseline is normal.
Phase 0 — Prereqs, target & mode (you, with Bash)
Working directory is already the mobile repo root — do not cd elsewhere; rely on relative paths.
Fail LOUD on any ambiguity below — never guess a baseline or target for the user.
- Submodule.
git submodule status. Ifupstream/missing:git submodule add https://github.com/LibreChat-AI/LibreChat.git upstream && git submodule update --init. - Version file.
cat UPSTREAM_VERSION. If missing, create fromversion.propertiesbackendTargetVersion+ submodule HEAD (tag=v<version>,commit=<HEAD>,date=$(date +%Y-%m-%d)). - Clean tree.
git status --porcelain. If dirty → ask the user to commit/stash; wait. - Baseline consistency (compute, then apply — a partial/rc baseline is NOT an inconsistency):
X.Y.Z+dev.<sha8>→<sha8>must be a prefix ofcommit=; verify the sha, not tag equality.X.Y.Z-rcN/ plainX.Y.Z→ must equaltag=withoutv.- Always: submodule HEAD must equal
commit=. - On failure → ask the user which state is the true baseline; wait. Never auto-pick.
- Fetch + resolve target.
cd upstream && git fetch origin --tags && git fetch origin dev main. Resolve$ARGUMENTS(see Target Modes) to a full{target_commit}:- none → newest stable tag (exclude
-rc/-beta/-alpha), but still enumerate newer rc tags and how fardev/mainare ahead (git rev-list --count {base_commit}..origin/dev) for the interview. - tag (stable or rc) → that tag; never silently drop an rc the user named.
- branch/SHA → partial;
{base_version}fromgit show {sha}:package.json,{anchor_tag}=git describe --tags --abbrev=0 --match "v[0-9]*" {sha}(--matchis required — upstream also tags Helm charts likechart-2.0.7).
- none → newest stable tag (exclude
- Detect mode. If
{target_commit}==commit=(submodule HEAD) or$ARGUMENTScontainsaudit→ audit mode; the audit base is the previouscommit=fromgit log -p --format=%H -- UPSTREAM_VERSION(or full-pin if--full). Else sync mode. If sync mode and no newer tags AND branch heads == base → tell the user "already up to date" and offer an audit instead of stopping. - Artifacts dir.
mkdir -p .claude/sync-upstream/artifacts. - Mirrored constants.
scripts/check-mirrors.py --from {base_commit} --to {target_commit} --diffSome upstream values are never served over the API, so the client hardcodes a copy — which providers take documents natively, which MIME types the parser extracts, which feedback reasons the write route accepts. These drift silently: nothing fails to decode, nothing errors, the app just makes worse decisions as it ages, so the ordinary diff sweep reads them as inert constant edits and defers them. Exit 1 means at least one moved; the output names the Kotlin file to reconcile. Exit 2 is not drift — it is a fatal (empty submodule, unresolvable revision, bad registry); fix the setup and re-run rather than reporting it as a finding. Carry every DRIFT and??row into the Phase 2 interview as its own item — a??means upstream renamed or deleted the symbol, so the registry entry is wrong either way. Theartifact-*rows are a different kind of mirror: what a React artifact mayimport(web's Sandpack dependencies, the shadcn components and their mount paths, the libraries the artifact prompt advertises). The client side is vendored JavaScript, not Kotlin, so they are reconciled with/update-web-assets(re-pin inscripts/artifact-modules/package.json, move the shadcn source URLs to the new commit,--sync), not by WF2's implementers. Also move those URLs whenUPSTREAM_VERSIONmoves, even if the rows areok: the shadcn-ui bundle's version is the upstream commit its sources came from. Seereference/upstream-paths.md, "Artifact runtime dependencies". Registry:scripts/mirrors.json. Adding a mirror to the codebase means adding an entry there in the same PR. Client transport contract.
packages/chat/src/core/(@librechat/chat, upstream #16964) is upstream's typedChatTransport(types.ts: send/reconnect/abort/status/resume/steer/queue, result variants, refusal codes,generationProtocolVersion) plus its reference SSE frame parser (transport/) and stream reducer (reducer.ts,steps/). It is the closest thing upstream has to a written spec of the streaming protocol this client implements, so diff it before anything else reads the range:cd upstream git cat-file -e {base_commit}:packages/chat/src/core/types.ts 2>/dev/null && echo base git cat-file -e {target_commit}:packages/chat/src/core/types.ts 2>/dev/null && echo target git diff {base_commit}..{target_commit} -- packages/chat/src/core/ \ > ../.claude/sync-upstream/artifacts/contract-diff.patchSet
contractState:absent— in neither commit. The range predates the package (landed 2026-10-10); continue.introduced— only in target. Every capability in the file is a candidate gap, not just a diff.changed— non-empty patch, otherwise. Iftypes.tsvanished from target, the contract moved: find where withgit log --diff-filter=R --statbefore passing it on.unchanged— in both, empty patch.
Watch the directory, not one file — the package is still landing as a PR stack and may split it. Pass
contractStateand the patch's absolute path into WF1, and carry its findings into the Phase 2 interview as their own group.
If a prior run's artifacts exist (ls .claude/sync-upstream/artifacts/), offer to resume from them.
Phase 1 — Discovery (WF1)
Invoke the discovery workflow. It runs the parallel multi-angle sweep, converges + cross-references
the mobile codebase, and runs a completeness critic. Watch its phase tree live via /workflows.
Workflow({ name: "sync-upstream-discovery", args: {
mode, baseCommit, targetCommit, targetMode, baseVersion, anchorTag,
skillDir: "<abs path to .claude/skills/sync-upstream>",
artifactsDir: "<abs path to .claude/sync-upstream/artifacts>",
contractState, // Phase 0 step 9
contractDiffPath: "<abs path to artifacts/contract-diff.patch>",
} })It returns { mode, range, findings[], counts, criticComplete, reportPath } and writes
artifacts/discovery-report.md. Each finding is machine-complete: category, severity, mobile-gap
status, iosMain coverage, landing commit + UTC landedDate, first-target-line, gate form. Do not
paraphrase-and-lose those — thread the structured objects straight into WF2.
Phase 2 — HITL interview (you)
This is the single human gate. Present the converged report, then use AskUserQuestion to settle:
- Target / scope (sync): confirm the resolved target or switch (stable / rc / partial — the findings are already tagged by target-line, so switching just filters). If the user switches, you have the data; no re-run needed unless they name a target outside the swept superset (then re-invoke WF1).
- Which items to implement now vs defer (Breaking + Security cannot be deferred — say so).
- Direction on UI items that don't map cleanly to Compose (surface the 2-3 options per item).
- Audit: which surfaced misses to fix now.
- Drifted mirrors (Phase 0 step 8): each one is a hand-maintained copy that upstream has moved underneath. They are cheap to reconcile and invisible if skipped — present them explicitly rather than folding them into the general findings list.
- Artifact dependencies (the
artifact-*mirror rows): name each package web added, dropped or re-pinned, and for each one added, its last release date and any advisories (the dependency policy applies). Ask per package: bundle it, bundle it behind the consent prompt (anadvisoryin its registry entry), or leave it unbundled (artifacts importing it show "not bundled"). Run/update-web-assetsfor the approved ones after WF2, on the same branch. - Transport contract (Phase 0 step 9): findings that trace to
packages/chat/src/core/, grouped by theChatTransportmember they touch. WhencontractStateisintroduced, say plainly which capabilities the client has no equivalent for yet. - Items marked
backend-blockedare shown as knowingly-skipped, never built.
Persist the approved, scoped list to artifacts/approved-{target}.md. If the user cancels, archive the
report and stop cleanly. Do not invoke WF2 until the user approves.
Phase 3 — Implementation (WF2)
Invoke the implementation workflow with the approved list. It implements per group, runs build + consistency gates, then ≥2 mandatory independent review passes (stateless ⇒ independent by construction; CONFIRMED vs PLAUSIBLE; iteration-capped). It ends at local commits — it never pushes.
Workflow({ name: "sync-upstream-implement", args: {
approvedItems, mode, targetMode, targetCommit, baseVersion, anchorTag,
targetTag, // release/rc only; null for partial
sha8, // partial only
bumpVersion, // FALSE in audit mode
branchName, // chore/sync-upstream-{tag} | -dev-{sha8} | -audit-{sha8}
skillDir, artifactsDir,
reportPath, // artifacts/discovery-report.md
} })Returns { branchName, buildResults, buildGreen, consistency, reviewPasses, reviewClean,
unresolvedConfirmed, testPlan }.
Then re-assert independently (you, with Bash) — do not trust the workflow's self-report blindly:
- sync:
sha8is a prefix ofcommit=;cd upstream && git rev-parse HEAD==commit=;BackendCommitMap.ktcontains the 12-char prefix ofcommit=(same checkrelease.ymlruns); README upper bound matches; eachsupportsFeaturerow'slandedDate≤ synced commit's UTC date. - audit: the pin did not move —
commit=,backendTargetVersion, submodule HEAD, andBackendCommitMap.ktare all unchanged from before the audit.
If buildGreen is false or unresolvedConfirmed is true, report it and route back into WF2 (scoped
to the failures) rather than proceeding.
Phase 4 — Test & push tail (you) — HARD STOP
Phase 3 ends at local commits. DO NOT push. DO NOT open a PR. Build + detekt + tests confirm scaffolding, not feature correctness. A sync must be device-tested against a real backend on BOTH Android and iOS (incl. older-server compat) before a PR is offered. The branch stays local-only until the user walks the test plan and explicitly says "push it" / "open the PR".
Present:
## Sync Ready for Device Testing: {baseline} → {target} [{mode}]
Branch `{branchName}` is local-only. Not pushed. No PR opened.
### Files changed {grouped by module}
### Test plan {WF2 testPlan — Android / iOS / compat}
### How to build & run Android: assembleDebug + install. iOS: linkDebugFrameworkIosSimulatorArm64, run in Xcode.
Connect to a target-version server + an older supported server; walk the plan.
Partial: verify new features HIDDEN on the older server, visible on a server the
regenerated BackendCommitMap COVERS (between landing and the pin). A server NEWER
than the pin resolves to no-version → features fail closed by design (not a bug),
and your own dev server drifts past the pin within days.
### Version updates {sync: the bumps; audit: "none — pin unchanged"}Then:
- User reports bugs → re-invoke WF2 scoped to just those fixes (same branch), loop until they're happy.
- User explicitly authorizes the push → only then run
git push/gh pr create. Not before.
Dispatch on-device test facilitation as needed (split by platform, or platform × feature area for large syncs). Device testing is the human's; you facilitate and route blockers back into WF2.
Reference files (read by the workflows' agents, not by you)
${CLAUDE_SKILL_DIR}/reference/: upstream-paths.md (diff surface), api-mapping.md,
model-mapping.md, ui-mapping.md, upstream-backend-gaps.md (client-only vapor features — do not
build), android-architecture.md (implementer patterns). Root: DISCOVERY.md, VERSION_GATES.md,
BackendVersion.kt, scripts/mirrors.json (hand-mirrored upstream constants — see Phase 0 step 8).
Error recovery
| Situation | Recovery |
| Submodule / UPSTREAM_VERSION missing | Recreate (Phase 0 steps 1–2) |
| Dirty tree / baseline inconsistency / SHA not found | Ask the user — never auto-resolve |
| Already up to date | Offer an audit (don't just stop) |
| No newer tags but dev/main ahead | Offer a partial sync |
| WF1/WF2 returns partial (agent died) | Re-invoke with resumeFromRunId (cached agents replay); artifacts under artifacts/ show the phase reached |
| BackendCommitMap missing the pin (release.yml net) | WF2's regen step runs AFTER submodule checkout; re-run if needed |
| Build/consistency/review fail | Reported in WF2's return; re-invoke WF2 scoped to the failures |
| Session compacted mid-run | Artifacts dir is the resume authority; resumeFromRunId only within a single workflow invocation |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

