Fork workflow: upstream mirror + product branch
kimi-seo is a fork of AgriciDaniel/claude-seo.
This document is the canonical reference for how work flows between upstream
and this fork. The step-by-step maintainer runbook that operationalizes it
lives at .agents/skills/seo-upstream-sync/SKILL.md.
Topology
upstream origin
AgriciDaniel/claude-seo bentocodeing/kimi-seo
│ │
│ git fetch upstream --tags │
▼ ▼
main (mirror) ───── merge ─────▶ kimi (product)
pristine copy of upstream + Kimi rebrand
upstream/main and adaptations
│
▼
releases tagged from kimi
- Remote
upstream=AgriciDaniel/claude-seo(read-only reference). - Remote
origin=bentocodeing/kimi-seo(this fork). - Branch
maintracks upstream untouched — a pristine mirror, fast-forward only. Never commit directly to it. - Branch
kimi= upstream + the Kimi rebrand and adaptations. All product work happens here; release tags are cut fromkimi.
Syncing from upstream
When upstream ships a new release:
- Pre-flight. Be on
kimiwith a clean working tree, thengit fetch upstream --tagsand check how far behind:git rev-list --count kimi..upstream/main. - Update the mirror.
Ifgit checkout main && git merge --ff-only upstream/main && git push origin main && git checkout kimi--ff-onlyfails,mainwas polluted — stop and investigate; do not force. - Merge into the product branch:
git merge upstream/main --no-ff. On conflicts, keep upstream's functional changes and the fork's naming per the invariants below. Hot spots:README.md,install.sh,install.ps1,.claude-plugin/plugin.json,pyproject.toml,skills/*/SKILL.md(description lines),docs/,.github/workflows/ci.yml(the fork triggers CI on[main, kimi]; upstream only hasmain— keep both entries),.gitignore(the fork drops the upstreamsite/ignore becausesite/hosts the Laravel website — never re-add it). - Re-apply the rebrand invariants after ANY merge (clean or not): scan the merge range for old branding and rebrand each hit except allowlisted attribution content.
The full runbook with exact commands, conflict-resolution rules, and abort
criteria: .agents/skills/seo-upstream-sync/SKILL.md.
Rebrand invariants (surface, not plumbing)
- NEVER rename: skill dirs/files under
skills/(allseo-*), agent files inagents/, script names inscripts/, internal paths. - MUST stay renamed: config dir
~/.config/kimi-seo, CLIbin/kimi-seo(andkimi-seo run|setup|doctorinvocations), display brand "Kimi SEO", fork repo URLsgithub.com/bentocodeing/kimi-seo, env varsKIMI_SEO_*. - MUST stay as-is (attribution):
github.com/AgriciDaniel/claude-seoURLs, "forked from" notes, CHANGELOG.md history, CONTRIBUTORS.md, CITATION.cff,skills/*/LICENSE.txtupstream URLs.
Verification gates (all must hold before any release step)
./bin/kimi-seo run check_rebrand.py→ PASS (exit 0). This includes the leaked-secret scan; if it fails, remove or relocate the offending content — never "fix" by allowlisting..venv/bin/python -m pytest tests/ -q→ green except the 2 knowntests/test_sync_flow.pyGitHub rate-limit failures../bin/kimi-seo run portability_check.py→ pass.
Releasing
- Bump the fork version on the fork's own semver line (not the upstream
number) in
kimi.plugin.json,pyproject.toml, and skill/agent metadata that carries it. - Update the
KIMI_SEO_TAGdefault ininstall.sh(andinstall.ps1). - Prepend a mapped entry in the "Kimi SEO fork releases" section of CHANGELOG.md: "Kimi SEO vX.Y.Z — based on upstream claude-seo vA.B.C".
- Tag from
kimiand push:git tag -a vX.Y.Z -m "Kimi SEO vX.Y.Z — based on upstream claude-seo vA.B.C" git push origin kimi --tags
Guardrails
- NEVER commit or push without explicit approval (the sync runbook's
push origin mainstep excepted). - NEVER force-push. NEVER rename skill/script/agent file names.
- If anything diverges from the runbook (non-ff main, dirty tree, unresolved conflicts), stop and report instead of improvising.