--- name: git-init description: >- Complete Git workflows on Windows for Gitea (and other hosts): init, signed Chinese commits, push, clone, pull, fetch, branch, merge, tag, stash, and Gitea SSH/GPG key verification challenges, using a local author profile, DPAPI-encrypted access token, SSH, and GPG. Use when the user asks to 初始化 Git, git init, Gitea, 验证密钥, 验证SSH, 验证GPG, 找不到此签名对应的密钥, 提交, commit, 推送, push, 克隆, clone, 拉取, pull, fetch, 分支, branch, 合并, merge, 标签, tag, stash, 远程推送, 配置远程仓库, 配置 SSH, 配置 GPG, 配置 Git Token, or uses the git-init skill. --- # git-init Windows PowerShell. Default remote host is **Gitea** (self-hosted or public). Do not use `eval "$(ssh-agent -s)"`. See [gitea.md](gitea.md) for URL forms, Token, SSH, and GPG on Gitea. Resolve `scripts/`: 1. Workspace `.cursor/skills/git-init/scripts` if it exists 2. Else `$env:USERPROFILE/.cursor/skills/git-init/scripts` 3. Else tell the user to run `install.ps1` from the git-skills repo and stop ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/.ps1" ``` Secrets live in `%USERPROFILE%/.git-skills/` (never in the project). ## Security red lines - Never read, print, or log `token.dpapi` or the **HTTPS access token** - Never put the HTTPS access token in chat, argv, README, `.env`, or git config - Never ask the user to paste the **HTTPS access token** into the conversation; use `store-token.ps1` on their machine - **Exception (Gitea key verify only):** you MAY ask for the short-lived **challenge token** shown on `/user/settings/keys` → 验证 (GPG and/or SSH). Do not store it. Do not confuse it with the access token - Do not run `store-token.ps1` or `store-profile.ps1` in the agent session - Never `--force` / `--force-with-lease` unless the user explicitly asked - Never `--no-verify` / skip hooks; never change an existing remote - Never set `--global` `user.name` / `user.email`. `credential.helper` may be global - Commit only when the user asked to commit/提交; push only when they asked to push/推送 - Never `reset --hard`, `rebase -i`, `push --delete`, or rewrite history unless the user explicitly asked ## Route | User intent | Path | | --- | --- | | 初始化 / git init / 配置远程 / 首次提交 | **Init** | | 提交 / commit | **Commit** (do not re-run init) | | 推送 / push / 远程推送 | **Push** | | 提交并推送 | **Commit** then **Push** | | 克隆 / clone | **Clone** — [workflows.md](workflows.md) | | 拉取 / pull / fetch | **Sync** — [workflows.md](workflows.md) | | 分支 / 切换 / 新建分支 | **Branch** — [workflows.md](workflows.md) | | 合并 / merge / rebase | **Merge** — [workflows.md](workflows.md) | | 标签 / tag | **Tag** — [workflows.md](workflows.md) | | stash / 暂存改动 | **Stash** — [workflows.md](workflows.md) | | 状态 / log / diff / 现在 git 怎么样 | **Inspect** (`repo-status.ps1`) | | 验证密钥 / 验证 SSH / 验证 GPG / 找不到此签名对应的密钥 / 开锁 | **Verify keys** (below) | If the folder is not a repo and the user asked to commit/push/pull/branch, run **Init** first (ask for remote URL if missing). Clone does not init the current folder. Examples: [examples.md](examples.md). ## Shared: profile + token ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/profile-status.ps1" powershell -NoProfile -ExecutionPolicy Bypass -File "/token-status.ps1" ``` - Profile `missing` → stop; user runs `store-profile.ps1` in their own terminal - Token `missing`/`invalid` → required for **Init** and for **HTTPS Push**; for **SSH Push** continue without token. User runs `store-token.ps1` in their own terminal when needed Do not ask for name/email/HTTPS access token in chat if the profile exists. # Verify keys (Gitea SSH + GPG) Proactive path when the user wants key verification, or Init finished adding keys, or UI shows 「找不到此签名对应的密钥」. ``` - [ ] Explain: open /user/settings/keys, click 验证 (challenge token ≠ access token) - [ ] Ask for GPG challenge token (and Key ID if unknown) - [ ] Ask for SSH challenge token - [ ] Run verify-gitea-keys.ps1 with tokens received - [ ] Show signature blocks; user pastes back into Gitea → 验证 - [ ] Remind: hard-refresh; only new commits show verified ``` **Ask in chat (required, do not wait for the user to invent the step):** 1. GPG: 「请打开 Gitea → 设置 → SSH/GPG 密钥 → 对应 GPG → 点验证,把页面上的令牌发给我(这是一次性挑战令牌,不是访问令牌)」 2. SSH: 「请再打开同一页的 SSH 密钥 → 点验证,把**另一个**页面令牌发给我」 When tokens arrive: ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/ensure-gpg.ps1" -Name "" -Email "" powershell -NoProfile -ExecutionPolicy Bypass -File "/verify-gitea-keys.ps1" -GpgToken "" -SshToken "" -KeyId "" ``` - Only GPG: `-GpgOnly -GpgToken "..."` - Only SSH: `-SshOnly -SshToken "..."` - Missing token → script prints `need_token` / `ask=...`; ask again and stop until answered Then paste the printed `BEGIN PGP SIGNATURE` / `BEGIN SSH SIGNATURE` blocks back to the user and tell them to click **验证** on Gitea. Do not claim verification succeeded until they confirm the UI shows 已验证. After both verified, ensure local signing: ```powershell git config user.signingkey "" git config commit.gpgsign true git config --unset gpg.format ``` Details: [gitea.md](gitea.md). # Init ``` - [ ] Detect - [ ] Profile + token - [ ] Remote URL + SSH/GPG - [ ] git init + local author - [ ] origin (do not overwrite) - [ ] Inject credentials - [ ] SSH - [ ] GPG - [ ] .gitignore + README - [ ] First signed Chinese commit - [ ] Push main - [ ] Verify ``` Detect: ```powershell git rev-parse --is-inside-work-tree git remote -v ``` If `origin` already exists: report remotes, switch to **Commit**/**Push** if that is what they wanted, and stop init. Do not change remotes. If the user did not give a remote URL, ask and wait. Default: reuse `~/.ssh/id_ed25519` and an existing GPG key. Generate only when missing. ```powershell git init -b main # skip if already a repo ``` Local author from `profile-status.ps1`: ```powershell git config user.name "" git config user.email "" git remote add origin "" git config --global credential.helper manager # only if unset powershell -NoProfile -ExecutionPolicy Bypass -File "/inject-credential.ps1" -RemoteUrl "" powershell -NoProfile -ExecutionPolicy Bypass -File "/ensure-ssh.ps1" -Email "" powershell -NoProfile -ExecutionPolicy Bypass -File "/test-ssh.ps1" -RemoteUrl "" powershell -NoProfile -ExecutionPolicy Bypass -File "/ensure-gpg.ps1" -Name "" -Email "" git config user.signingkey "" git config commit.gpgsign true ``` Show the **public** SSH key. Tell the user to add it in Gitea: **设置 → SSH / GPG 密钥**. Run `test-ssh.ps1` (supports custom SSH ports from the URL). Status `ok` even if ssh exits 1 when the message contains `Hi there` / `successfully authenticated` / `Welcome to Gitea`. If auth fails, wait for the user to add the pubkey. **Gitea key verification is required** (official: unverified keys → 「找不到此签名对应的密钥」). After keys are added, go to **Verify keys**: **proactively ask** for the GPG and SSH challenge tokens from `/user/settings/keys` → 验证, then run `verify-gitea-keys.ps1`. Prefer OpenPGP for commits (`user.signingkey` = Key ID; do not set `gpg.format=ssh` unless the user wants SSH commit signing). Guide: [gitea.md](gitea.md). Official: https://docs.gitea.com/administration/signing/ Ensure `.gitignore` contains: ``` .git-skills/ *.dpapi .env .env.* *.pem id_rsa id_ed25519 id_ecdsa ``` Create `README.md` only if missing (项目简介 / 基础使用说明 / 项目结构 / 开发说明). Do not overwrite. Then **Commit** with message `初始化: 完成项目Git配置` if there is no commit yet, then **Push** `main` (`git branch -M main` first). Verify with the Push/Commit verify steps. # Commit (every time) Do this for the first commit and every later commit. Do not re-init. ``` - [ ] prepare-commit - [ ] GPG key if signing=missing - [ ] status / diff / log - [ ] assert-no-secrets - [ ] Stage related files only - [ ] Signed Chinese commit - [ ] Verify signature - [ ] Push only if asked ``` ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/prepare-commit.ps1" ``` If `signing=missing`: ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/ensure-gpg.ps1" -Name "" -Email "" git config user.signingkey "" powershell -NoProfile -ExecutionPolicy Bypass -File "/prepare-commit.ps1" ``` Then: ```powershell git status git diff git diff --staged git log -5 --oneline powershell -NoProfile -ExecutionPolicy Bypass -File "/assert-no-secrets.ps1" ``` If `assert-no-secrets` is `blocked`, unstage those paths and do not commit them. Stage **only related files**. Do not `git add -A` on later commits unless the user asked to commit everything. Init may `git add -A` after `.gitignore` is in place. If there is nothing to commit, stop. Do not create an empty commit. Message must be Chinese `类型: 描述`. Types: `初始化` / `新增` / `修复` / `优化` / `文档`. Infer from the diff; if the user gave a message, rewrite it into this format. Forbidden: `update` / `fix` / `test` / `修改一下`. Details: [reference.md](reference.md). **Every commit must include `Co-authored-by` trailers** from the local profile (primary author always; plus optional `coAuthors`). Do not invent co-authors. Prefer profile author over any IDE default. If Cursor also appends `Co-authored-by: Cursor <...>`, keep the profile trailers from `emit-commit-message.ps1` (do not drop them). Build the message with: ```powershell $subject = "类型: 描述" $msg = & powershell -NoProfile -ExecutionPolicy Bypass -File "/emit-commit-message.ps1" -Subject $subject | Out-String git commit -S -m $msg.TrimEnd() ``` Equivalent shape (must keep a blank line before trailers): ``` 类型: 描述 Co-authored-by: 旅行呀~ ``` Always `-S`. Never strip `Co-authored-by` lines. Never `--amend` unless the user asked and the HEAD commit is yours, unpushed, and no hook failed. ```powershell git status git log --show-signature -1 git log -1 --format=%B ``` Confirm the body contains `Co-authored-by:` and author is `姓名 <邮箱>` from the profile. If the user also asked to push, continue to **Push**. # Push (every time) Do this for the first push and every later push. Do not re-init. Do not commit during Push unless the user also asked to commit. ``` - [ ] prepare-push - [ ] Push current branch - [ ] Verify ``` ```powershell git status -sb git remote -v powershell -NoProfile -ExecutionPolicy Bypass -File "/prepare-push.ps1" ``` If `remote_missing`, ask for a URL and go to **Init** step “Add origin”, then retry. If HTTPS `token_missing`, stop and tell the user to run `store-token.ps1`. ```powershell git branch --show-current git rev-parse --abbrev-ref --symbolic-full-name '@{u}' ``` - No upstream: `git push -u origin HEAD` - Upstream exists: `git push` - After init, `main` may not exist yet: `git branch -M main` then `git push -u origin main` - Never `--force` unless explicitly requested (warn that it rewrites remote history) - Never push to a different remote/branch than the user named ```powershell git status -sb git log --show-signature -1 ``` # Clone / Sync / Branch / Merge / Tag / Stash / Inspect Read [workflows.md](workflows.md) and follow that path. Network ops always run auth first: ```powershell powershell -NoProfile -ExecutionPolicy Bypass -File "/repo-status.ps1" powershell -NoProfile -ExecutionPolicy Bypass -File "/prepare-auth.ps1" -RemoteUrl "" powershell -NoProfile -ExecutionPolicy Bypass -File "/prepare-push.ps1" ``` - **Clone**: `prepare-auth` then `git clone`; then `prepare-commit` inside the clone (do not commit unless asked) - **Pull**: `prepare-push` then `git pull --ff-only`. If it fails, stop and report divergence; do not force - **Inspect**: `repo-status.ps1` plus `git status` / `diff` / `log --show-signature`; read-only ## Additional resources - Gitea URLs, Token, SSH/GPG verify: [gitea.md](gitea.md) - Commit types, Windows SSH/GPG, troubleshooting: [reference.md](reference.md) - Clone, pull, branch, merge, tag, stash, inspect: [workflows.md](workflows.md) - Trigger examples: [examples.md](examples.md)