fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery

Claude Code's (and Copilot's) native plugin installer has zero awareness of
.apm/ nesting -- it convention-scans only flat skills/, agents/, commands/,
hooks.json at each plugin's root. Confirmed via strings on the installed
claude binary and live installs of git@holocron/gitea@holocron/kyberforge@
holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm
conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json
compiler deliberately strips skills/agents/commands keys, assuming the host
already auto-discovers those convention directories -- it has no model of
.apm/ being host-visible at all. Separately, apm's own bundle exporter
(apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`)
implements the correct .apm/ -> flat mapping, but only ever targeted
build/<name>-<version>/, a path nothing in marketplace.json's source: points
at.

scripts/sync-plugin-content.sh wraps that bundle exporter and copies its
agents/, skills/, commands/, instructions/, extensions/, and merged
hooks.json back into each plugin's own root as a second tracked
compiled-output category -- same governance status as
.claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/
subdirectories are excluded from the mirror (dev fixtures, not host-visible
runtime content; several hardcode a relative repo-root walk-up sized for the
.apm/-nested depth, which breaks when duplicated one level shallower).
Applied for real across all 6 plugins and verified two ways: `claude plugin
validate --strict` passes on every real plugin directory, and a live
`claude --plugin-dir <path> -p "list skills/agents"` behavioral test
confirms content is now actually discovered.

Also, from the same issue #90 review round:
- scripts/check-manifests.sh pointed at each plugin's root-level plugin.json
  (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a
  stale near-duplicate of .claude-plugin/plugin.json nothing else read or
  wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to
  validate .claude-plugin/plugin.json instead, and drops the pointer-field
  checks entirely (nothing to check -- those fields are correctly absent by
  design). Content-presence drift is now check-plugin-content-sync's job, a
  new pre-push hook wired in .pre-commit-config.yaml.

docs/adr/0017 records the root cause and decision in full, including two
rejected alternatives (patching plugin.json's path fields directly -- apm's
compiler strips them on every run; pointing marketplace.json at apm pack's
build/ output -- a version-suffixed non-source directory nothing can install
from without an extra build step). ADR-0015 and CONTEXT.md are updated to
point at it.

Refs: #90
This commit is contained in:
2026-08-13 16:59:03 +00:00
parent 7910b8b12c
commit 38f1ba4e03
217 changed files with 14455 additions and 175 deletions

View File

@@ -0,0 +1,90 @@
---
name: git-orchestrate
description: Orchestrates git workflow operations for other agents. Invoke when a caller needs a multi-step or destructive git operation (rebase, force-push, branch deletion) coordinated across domain skills with safety gates, session context, and structured results.
source_keys:
- context7-git-htmldocs
- git-scm-docs
- git-scm-worktree-docs
- git-scm-submodule-docs
- git-scm-remote-docs
- conventional-commits-spec
---
You are the orchestrator for the git plugin—a composable workflow dispatcher designed for other agents to invoke multi-step git operations reliably. Your one job is routing and safety-gating: you do not execute git logic yourself, you delegate to domain skills and enforce confirmation on destructive operations.
You act on the caller's real branch and session context (you explicitly carry forward `current_branch`), not a disposable copy — you do not run in an isolated worktree.
**Scope:** this orchestrator routes git-object operations only (commits, branches, worktrees, remotes, submodules, history). `pc-author` and `pc-run` (pre-commit config authoring and hook execution) are intentionally not routed here — they operate on `.pre-commit-config.yaml` and hook installation, not git objects. `git-workflow` is also not routed here, but for a different reason than `pc-author`/`pc-run`: it is a human-facing conversational wrapper for all git operation types (commits, branches, history, submodules, worktrees, remotes), and it itself calls this orchestrator internally as its execution backend — its own workflow explicitly invokes the `git-orchestrate` agent as its final step. It is not a peer to invoke instead of this dispatcher, and it explicitly refuses agent callers ("Do not use when the caller is an agent"). Agent callers route git-object operations here directly; direct human users to `git-workflow` when they want guided, conversational git help — it will call back into this orchestrator itself. Invoke `pc-author`/`pc-run` directly rather than through this dispatcher; do not invoke `git-workflow` as an agent caller under any circumstance.
## Hard rules
These are non-negotiable regardless of `confirm` or any skill-local override:
- Never skip hooks with `--no-verify`. Hooks are the automated QA gate; bypassing them breaks the pipeline.
- Never force-push `main` or `master`.
- Keep commits atomic — one logical, independently reviewable and reversible change per commit.
- Every commit must leave the repository in a working state (buildable/testable where practical).
- Commit messages explain **why**, not **what** — the diff already documents what changed.
- Use Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`, etc.).
- Never commit secrets, credentials, or environment-specific config.
- Reference related issues, ADRs, or design documents using git trailers (`Fixes:`, `Refs:`, `ADR:`, `RFC:`, `Design:`) when applicable.
### Submodule ordering
- Commit and push the submodule first, then update and push the parent repo. Pushing the parent before the submodule commit exists on the remote breaks `git submodule update` for anyone who pulls.
- Always use `rtk git` for parent-repo operations; drop into the submodule directory and use bare `git` for submodule-specific commands.
- After adding or updating a submodule, check `git status` in both the parent and the submodule — a `-dirty` flag means the submodule has uncommitted local changes that must be committed before the parent pointer updates.
Sub-skills carry their own local copies of these rules for humans who invoke them directly, bypassing this orchestrator. When a caller routes through you, this section is the enforcement backstop: check every routed operation against it before dispatch, not just the destructive-operation confirm gate below.
When invoked, you:
1. Parse the incoming workflow request (operation type, parameters, context overrides)
2. Check safety gates: if the operation is destructive (force-push, branch deletion, rebase with history loss, force-checkout) and the request lacks explicit `confirm: true`, fail immediately with "requires explicit confirmation"; force-push to `main`/`master` is refused outright regardless of `confirm`
3. Route to the appropriate domain skill: `git-commits`, `git-branches`, `git-history`, `git-submodules`, `git-worktrees`, `git-remotes`
4. Manage session context: carry forward the current branch, workflow intent, and configuration, passing explicitly to each skill
5. Handle error recovery: for recoverable failures (merge conflicts, push rejections, auth issues), attempt automatic recovery; if unrecoverable, fail gracefully with actionable diagnostics
6. Aggregate results and return structured JSON output suitable for agent chaining
## Inputs
- **operation:** string, one of:
- commits/history: commit, amend, cherry-pick, rebase, squash, blame, log
- branches: create-branch, switch-branch, delete-branch, rename-branch, track-branch, list-branches
- worktrees: create-worktree, list-worktrees, lock-worktree, unlock-worktree, move-worktree, remove-worktree, prune-worktree, repair-worktree
- remotes: add-remote, remove-remote, rename-remote, set-remote-url, push, pull, fetch
- submodules: add-submodule, init-submodule, update-submodule, sync-submodule, remove-submodule, submodule-status
- **parameters:** object, operation-specific arguments (branch name, commit message, etc.)
- **context:** object (optional), workflow state to carry forward (current_branch, branch_intent, user_config_overrides)
- **confirm:** boolean (optional), explicit confirmation for destructive operations (required if not set for force-push, branch deletion, rebase with history loss, force-checkout)
## Process
1. Validate the request structure and check if operation is known
2. Check the request against the Hard rules above (no `--no-verify`, no force-push `main`/`master`, atomicity, submodule ordering, etc.) — refuse outright on violation, independent of `confirm`
3. If destructive operation: require `confirm: true`, else fail with structured "requires explicit confirmation" error
4. Read plugin config from `.claude/plugins/git/config.json` if present — see `config.example.json` in the plugin root for the expected shape (`branching_pattern`, `commit_style`, `rebase_strategy`) — or fall back to sensible defaults
5. Invoke the appropriate skill via `Skill` or direct bash call with the operation, parameters, context, and config. For parent-repo git invocations, use `rtk git` rather than bare `git` (per org convention); submodule-specific commands run as bare `git` inside the submodule directory (see Submodule ordering above).
6. Catch and handle git errors: attempt automatic recovery (offer rebase strategies for conflicts, suggest `--force-with-lease` for rejections)
7. If recovery succeeds, continue; if not, return error structure with diagnostics and suggestions
8. Aggregate all outputs and return as structured JSON
## Output
```json
{
"status": "success" | "error",
"operation": "<operation_name>",
"result": {
"output": "<command output or result>",
"context": { "current_branch": "...", "workflow_intent": "..." },
"applied_config": { "commit_style": "...", "rebase_strategy": "..." }
},
"error": {
"message": "<human-readable error>",
"code": "<error type: conflict | auth_failure | push_rejection | invalid_state>",
"recovery_attempted": true | false,
"suggestions": ["<suggestion1>", "<suggestion2>"]
}
}
```

View File

@@ -1,17 +0,0 @@
{
"author": {
"email": "defame1297@rkdr.net",
"name": "Defame1297",
"url": "https://git.dev.rkdr.net/Defame1297/"
},
"description": "Skills for working with Git \u2014 conventional commits, branch management, pull requests, and feature flow.",
"keywords": [
"git",
"vcs",
"commit",
"branch"
],
"license": "MIT",
"name": "git",
"version": "1.3.2"
}

View File

@@ -0,0 +1,22 @@
# git-branches
Manage the full lifecycle of git branches — create, switch, delete, rename, and track feature/hotfix/release branches under GitHub Flow or Gitflow.
## What it does
This skill handles branch operations within the git workflow suite. It creates branches following GitHub Flow or Gitflow conventions (configurable), switches and tracks branches, handles safe deletion with unmerged-work checks, and retrieves branch intent metadata for use by other skills (e.g., commit message context). It returns structured results suitable for agent composition.
## Usage
```
/git-branches
```
Describe your branch task: create a feature/hotfix/release branch, switch, delete, rename, or track. The skill will determine the branching pattern (GitHub Flow or Gitflow) from config or repo state and handle safety checks for destructive operations.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/sources.md` | Research sources backing the branching/gitflow guidance |

View File

@@ -0,0 +1,112 @@
---
name: git-branches
description: >
Use when managing the full lifecycle of git branches: create feature/hotfix/release branches
(gitflow, GitHub Flow, or custom patterns from config), switch, delete, rename, and track branches,
or retrieve branch intent metadata. Handles branch protection safety checks and returns structured
results for agent composition. Use even if the user doesn't explicitly mention branch names — they
may be asking about "fixing something" or "shipping a feature", which implicitly requires branch
management. Do not use when the user needs only commit operations (use git-commits) or history
inspection (use git-history).
metadata:
category: git
source_keys:
- context7-git-htmldocs
- nvie-gitflow-post
- atlassian-gitflow-tutorial
- gitflow-cheatsheet
---
## Gotchas
- **Branches are cheap; deletion is cheap but risky.** Deleting one requires checking if commits on it are reachable elsewhere; always confirm before deleting, as it may lose unmerged work.
- **Uncommitted changes can block branch switches.** `git switch` aborts if local modifications conflict with the target branch. Offer to stash changes before switching when this happens, don't force a checkout.
- **Tracking relationships matter for coordination.** Agents pushing on behalf of users should always set tracking (`-u origin <branch>`) so later pushes/pulls know the target. Without it, commands fail or target the wrong remote branch.
- **Gitflow vs. GitHub Flow are not compatible.** Gitflow requires `develop` and `release/*` branches with `--no-ff` merges; GitHub Flow uses only `main` and feature branches with fast-forward. Read the repo's config or ask the orchestrator which pattern to use — don't guess.
- **Naming collisions with tags.** A branch and tag can have the same name. Prefer `git switch` over `git checkout` for branch operations — verify which ref you're targeting with `git branch --list <name>` / `git tag --list <name>` if the name could be ambiguous, and disambiguate explicitly with `refs/heads/<name>` (branch) or `refs/tags/<name>` (tag) where a command accepts either.
- **Never force-push `main` or `master`.** This is a hard refusal, not a confirmation gate — it applies even if the caller passes `confirm: true`. Deleting or renaming `main`/`master` in a way that would require a force-push to reconcile the remote (e.g. force-deleting and recreating it, or renaming it out from under in-flight work) must be rejected outright; explain why and suggest a non-destructive alternative (e.g. a new branch) instead of proceeding.
## Branch Patterns
Default to **GitHub Flow** (simpler, modern, CI/CD-friendly). Fall back to **Gitflow** only if the repo's config specifies it or the branch structure shows it in use (presence of `develop` or release branches).
**GitHub Flow:**
- Base: `main`
- Feature branches: `feature/<feature-name>` or `fix/<bug-name>`
- Merge: fast-forward when possible (preserves linear history)
- Delete after merge
**Gitflow:**
- Base: `main` (production) + `develop` (integration)
- Feature branches: `feature/<feature-name>` (from `develop`)
- Release branches: `release/X.Y.Z` (from `develop`, merged to `main` + `develop`)
- Hotfix branches: `hotfix/X.Y.Z` (from `main`, merged to `main` + `develop`)
- Merge: always use `--no-ff` to preserve branch structure
## Workflow
- [ ] **Determine pattern:** Check git plugin config (`.claude/plugins/git/config.json`, if present — see `config.example.json` in the plugin root for the expected shape) for `branching_pattern` (default: `github-flow`). If not set, inspect repo for `develop` branch or `release/*` branches; if present, assume Gitflow.
- [ ] **Create branch:** Use `git switch -c <branch> <base>`. Base defaults to config's `base_branch` (usually `main` or `develop`). Include intent metadata in branch name or return as structured result (e.g., `{ "branch": "feature/x", "intent": "implement feature X" }`).
- [ ] **Track remote:** If pushing, always use `git push -u origin <branch>` to establish tracking.
- [ ] **Safety checks before destructive ops:** Before delete/force-push/rebase with history loss, check: (1) Is this branch tracking a remote? Warn if yes. (2) Are there unpushed commits? Warn if yes. (3) Does the orchestrator call include `confirm: true`? Fail if not. For humans, prompt interactively.
- [ ] **Return structured results:** Always return branch operations as JSON or structured text: `{ "action": "create", "branch": "feature/x", "base": "main", "tracking": "origin/feature/x", "intent": "implement feature X" }`. Agents need to parse this for subsequent operations.
- [ ] **Retrieve intent (`get-intent`):** Git has no native field for free-text branch metadata — this skill doesn't persist it. On `create`, the `intent` value is only ever returned in the structured result; the caller (orchestrator or agent) is responsible for storing it if it needs to be looked up later. On `get-intent`, either parse it back out of the branch name convention (`feature/<intent-slug>`) or return `{ "intent": null }` if the caller never persisted the original create-time value — don't fabricate an intent.
### Command mapping for each action
- **delete:** `git branch -d <branch>` refuses if the branch has unmerged commits — prefer this by default. `git branch -D <branch>` forces deletion and discards unmerged work; only use it after the safety checks above pass and `confirm: true` is set. For a remote branch: `git push origin --delete <branch>`.
- **rename:** `git branch -m <old> <new>`.
- **list:** `git branch` (local only), `git branch -a` (all local + remote-tracking), `git branch -r` (remote-tracking only), `git branch --merged`/`--no-merged` (filter by merge status into current branch).
- **get-intent:** No git command — see Workflow step "Retrieve intent" for how this is resolved.
- **track (existing branch):** `git branch --set-upstream-to=origin/<branch>` sets tracking without a push; `git branch -vv` shows tracking state for all local branches.
- **switch (existing branch):** `git switch <branch>` — switches to an existing local branch (aborts on conflicting local changes, see Gotchas). `git switch -` switches back to the previously checked-out branch.
## Merging
Scope: fast-forward/merge-commit mechanics and conflict resolution only. Rebase, cherry-pick, and revert belong to `git-history`.
- **Fast-forward:** `git merge <branch>` — advances the pointer with no merge commit if the target hasn't diverged.
- **True merge:** `git merge --no-ff <branch>` — forces a merge commit even when fast-forward is possible; required by Gitflow on all supporting-branch merges.
- **Squash merge:** `git merge --squash <branch>` stages the combined diff without committing; follow with a manual `git commit`.
- **Octopus merge:** `git merge branch-a branch-b branch-c` merges more than two branches at once; fails outright on any conflict, so use sequential two-way merges if conflicts are expected.
**Conflict resolution:** when Git can't auto-merge, it inserts conflict markers and stops. Run `git status` to find conflicted files, edit them to resolve the markers, then `git add <file>` and `git merge --continue`. `git merge --abort` reverts to the pre-merge state. `git mergetool` opens the configured merge tool; `git diff --diff-filter=U` shows only conflicted files.
## Comparing Branches
- `git log main..feature` — commits in `feature` not in `main`.
- `git log feature..main` — commits in `main` not in `feature` (reverse direction).
- `git log --left-right main...feature` — both diverging sets (symmetric diff).
- `git diff main...feature` — diff from the common ancestor to `feature`'s tip.
- `git merge-base main feature` — print the common ancestor commit.
## Integration with Orchestrator
When invoked by `git-orchestrate`, accept requests in the form:
```json
{
"action": "create|switch|delete|rename|track|list|get-intent",
"branch": "<branch-name>",
"base": "<base-branch (optional, defaults to config)>",
"intent": "<human-readable intent (optional)>",
"confirm": "<true for destructive ops, omit for read ops>"
}
```
Return results as:
```json
{
"success": true,
"action": "create|switch|...",
"branch": "<name>",
"message": "descriptive message",
"intent": "<intent if tracked>",
"tracking": "origin/<branch (if set)>",
"error": "<error message if success=false>",
"suggestion": "<recovery suggestion if applicable>"
}
```
If error is due to uncommitted changes, include `{ "suggestion": "stash changes and retry" }` so the orchestrator can offer automatic recovery.

View File

@@ -0,0 +1,48 @@
---
# Research sources referenced by this skill
# Each entry documents where the skill's guidance came from.
---
## nvie-gitflow-post
**Description:** Original 2010 post by Vincent Driessen introducing the Gitflow branching model, including a 2020 reflection note recommending GitHub Flow for continuous delivery teams.
**Source:** https://nvie.com/posts/a-successful-git-branching-model/
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Branch Patterns — Gitflow vs. GitHub Flow structure and defaults)
## atlassian-gitflow-tutorial
**Description:** Atlassian's comprehensive Gitflow tutorial covering all five branch types, lifecycle steps, and CLI usage.
**Source:** https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Branch Patterns — Gitflow branch types, base/merge targets, `--no-ff` requirement)
## gitflow-cheatsheet
**Description:** Visual cheatsheet for the git-flow CLI commands (git-flow-avh fork), covering all subcommands for feature, release, and hotfix branches.
**Source:** https://danielkummer.github.io/git-flow-cheatsheet/
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Branch Patterns — feature/release/hotfix naming conventions)
## context7-git-htmldocs
**Description:** Official Git HTML documentation from the git/htmldocs repository — covers all commands, concepts, and internals.
**Source:** context7:/git/htmldocs
- **Research doc:** plugins/git/docs/research/docs/git/branching-merging.md (whole-document reference)
**Contributing files:**
- SKILL.md (Command mapping, Merging, Comparing Branches — `git switch`/`git branch`/`git merge`/`git log`/`git diff`/`git merge-base` command vocabulary and flags)

View File

@@ -0,0 +1,24 @@
# git-commits
Create, amend, squash, and cherry-pick commits with Conventional Commits formatting and validation.
## What it does
This skill handles commit operations within the git workflow suite. It generates well-formatted commit messages following the Conventional Commits spec, validates against commitlint config-conventional constraints, and communicates SemVer impact. It enforces confirmation gates for history-altering operations (amend, rebase, squash) and returns structured JSON output for agent consumption.
## Usage
```
/git-commits
```
Describe your commit task: create a new commit, amend, squash, or cherry-pick. The skill will guide message formatting and handle confirmation for destructive operations.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/conventional-commits-spec.md` | Full Conventional Commits specification |
| `references/commit-template.md` | Why / Implementation Notes / Impact body structure and full trailer list |
| `references/sources.md` | Research sources and provenance |

View File

@@ -0,0 +1,115 @@
---
name: git-commits
description: >
Use when creating, amending, squashing, or cherry-picking commits.
Generates well-formatted commit messages following Conventional Commits spec (type, scope, description, body, footers).
Validates against commitlint config-conventional constraints (header max 100 chars, lowercase subject, no trailing periods, type must be one of 11 standard types).
Communicates SemVer impact (MAJOR for breaking changes, MINOR for features, PATCH for fixes).
Handles confirmation gates for history-altering operations (amend, rebase, squash).
Provides interactive guidance for humans, structured JSON output for agents.
Do not use for: inspecting git history, branch management, or repository state inspection — those are separate skills.
metadata:
version: "0.1.2"
category: git
source_keys:
- conventional-commits-spec
- commitlint-config-conventional
- org-commit-conventions
- context7-git-htmldocs
allowed-tools: Bash
---
## Gotchas
- **Type must be one of 11 standard types** — `feat`, `fix`, `perf`, `revert`, `docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore`. Non-standard types will fail commitlint validation. Note: the Conventional Commits spec itself only mandates `feat`/`fix` — the 11-type set is a commitlint/Angular convention this skill validates against, not a spec requirement.
- **Scope is optional but should be used** — helps identify which part of the system changed. Examples: `api`, `db`, `cli`, `config`.
- **Header max 100 characters** — type + scope + colon + description must fit. If longer, move detail to body.
- **BREAKING CHANGE notation** — use `!` before the colon (`feat!: drop Node 6`) for visibility in `git log --oneline`. Footer notation (`BREAKING CHANGE: ...`) is machine-readable but hidden in log.
- **SemVer mapping is not optional** — agents must communicate: `feat` → MINOR bump, `fix`/`perf`/`revert` → PATCH, any with breaking change → MAJOR.
- **Confirmation gates are mandatory for destructive operations** — amend, rebase, squash require explicit user/agent approval before execution.
- **Never skip hooks with `--no-verify`** — hooks are the automated QA gate; bypassing them breaks the pipeline. Do not add this flag to any commit command unless the user explicitly demands it, and warn them if they do.
- **Never force-push `main`/`master`** — even after an amend or interactive rebase, refuse to force-push a protected branch (`main`, `master`) and explain why; force-push is only safe on branches no one else has based work on.
- **Command examples use the `rtk git` wrapper** — this org's convention routes all git invocations through `rtk git <subcommand>` instead of bare `git <subcommand>`. Follow this prefix in any command you actually run.
- **Never commit secrets, credentials, or environment-specific config** — if staged changes contain what looks like an API key, token, password, or connection string, stop and flag it before committing rather than committing it.
- **Commits must be atomic and leave the repo working** — each commit should be one logical, independently reviewable and reversible change, and should leave the repository in a buildable/testable state. If staged changes bundle unrelated work, suggest splitting before committing.
- **Commit messages explain why, not what** — the diff already shows what changed; the message's job is to capture context the diff can't (motivation, root cause, tradeoffs). See `references/commit-template.md` for the structure this maps to.
## Workflow
### For creating a new commit:
1. **Gather context** — what changed and why? (from staged changes, PR description, issue context). Verify the staged diff is one logical, atomic change and that the repo would still build/test at this commit — if not, suggest splitting before proceeding.
2. **Check for secrets** — scan the staged diff for anything that looks like a credential, API key, token, or environment-specific config. Stop and flag it rather than committing.
3. **Determine type** — is this a feature (`feat`), bug fix (`fix`), or other? Default: check the change itself.
4. **Determine scope** — which system/module? Use scope from plugin config if set, otherwise infer from files changed.
5. **Write description** — imperative mood, no period. Neither source spec sets a length target below the 100-char header max, but convention favors keeping it to ~50 characters where possible for `git log --oneline` readability. Examples: "add user authentication", "fix race condition in cache".
6. **Add body if needed** — explain why (not what). Blank line before body, wrap at 100 chars. For non-trivial changes, follow the Why / Implementation Notes / Impact structure in `references/commit-template.md`.
7. **Add footers if needed** — `Fixes: #123`, `Refs: #123`, `ADR: 0012`, `RFC: 0003`, `Design: <link>`, `Reviewed-by: Name`, `Co-authored-by: Name <email>`, `Signed-off-by: Name <email>`, `BREAKING CHANGE: description`. See `references/commit-template.md` for the full trailer list.
8. **Validate** — check header length, type correctness, no trailing periods, lowercase.
9. **Confirm and execute** — for agents, require explicit approval; for humans, show preview and ask. Never add `--no-verify` to skip hooks.
### For amending a commit:
1. **Stage new changes** (or changes to undo)
2. **Run amend operation** — executes `rtk git commit --amend [--no-edit]` based on user intent
3. **Offer message edit** — if user wants to change commit message, show current message and prompt for new one
4. **Confirm before force-push** — amending is only safe on non-shared branches; if the current branch is `main`/`master`, refuse to force-push and explain why rather than warning and proceeding
### For squashing commits (interactive rebase):
1. **Identify commits to squash** — typically the last N commits on current branch
2. **Confirm operation** — squashing rewrites history; get explicit approval
3. **Execute rebase** — `rtk git rebase -i HEAD~N`, mark older commits as `squash` or `fixup`
4. **Handle merge conflicts** — if rebase halts, offer conflict resolution options or abort; do not resolve automatically without confirmation
5. **Offer message composition** — if squashing interactive, allow message editing
### For squashing commits (autosquash — preferred when tagging at commit time):
Prefer this over manual interactive rebase when a commit is written to be folded into an earlier one, since it removes the manual "mark as squash/fixup" step and the risk of reordering the wrong line:
1. **Create the fixup/squash commit** — `rtk git commit --fixup=<commit>` (keeps target's message) or `rtk git commit --squash=<commit>` (lets you edit the combined message later). Both prefix the message with `fixup!`/`squash!` and target `<commit>`.
2. **Confirm operation** — rewriting history still requires explicit approval before the rebase runs.
3. **Execute** — `rtk git rebase --autosquash HEAD~N` (or `-i --autosquash` to review the plan first); git reorders and marks the `fixup!`/`squash!` commits against their targets automatically.
4. **Handle merge conflicts** — same as manual rebase: offer resolution or abort, never resolve automatically without confirmation.
### For cherry-picking:
1. **Identify source commit(s)** — hash or branch reference
2. **Confirm destination branch** — cherry-pick will replay commits on current branch
3. **Execute cherry-pick** — `rtk git cherry-pick <commit-hash>`
4. **Handle conflicts** — offer conflict resolution or abort
5. **Report outcome** — successful replays, conflicts, or rejected commits
## Output format (for agent consumption)
Return structured JSON:
```json
{
"operation": "create|amend|squash|cherry-pick",
"status": "success|conflict|rejected",
"message": "Commit message or error description",
"commit_hash": "abc1234",
"semver_impact": "MAJOR|MINOR|PATCH|none",
"breaking_change": true|false,
"confirmation_required": true|false,
"details": {
"type": "feat",
"scope": "api",
"description": "add user authentication",
"body": "optional body text",
"footers": ["Fixes: #123", "Refs: #456", "ADR: 0012", "Reviewed-by: Alice", "Co-authored-by: Bob <bob@example.com>", "Signed-off-by: Alice <alice@example.com>"]
}
}
```
For interactive human use, format as readable prose with clear prompts and previews.
## Reference
If a footer or type/scope edge case isn't covered above, read `references/conventional-commits-spec.md` for the full specification.
For the Why / Implementation Notes / Impact body structure and the full trailer list, read `references/commit-template.md`.

View File

@@ -0,0 +1,66 @@
---
source_keys:
- org-commit-conventions
---
# Commit Message Body Template
Use this structure for the body/footer of any non-trivial commit (skip sections that don't apply — do not leave placeholders in the actual commit).
```
<type>(<scope>): <concise summary>
```
The header is required. Describe the intended outcome, not the implementation.
## Why
Explain why this change exists. This is the most valuable part of the commit — the diff already shows *what* changed; future maintainers (human or AI) need *why*.
Include, where applicable:
- Problem being solved
- User or business need
- Bug or root cause
- Important context not visible in the code
Omit if the reason is immediately obvious.
## Implementation Notes
Capture decisions that are difficult to infer from the code:
- Why this approach was chosen
- Important assumptions or invariants
- Constraints imposed by external systems
- Tradeoffs or intentional compromises
- Non-obvious implementation details
- Workarounds or temporary solutions
Do NOT describe the diff ("renamed X", "added Y"). Omit if there's nothing worth preserving.
## Impact
Document effects future developers should know about:
- Behavior changes
- Breaking changes
- Performance implications
- Security considerations
- Migration or deployment requirements
- Compatibility concerns
- Follow-up work or known limitations
Omit if there are no noteworthy impacts.
## Trailers
Structured metadata for traceability and tooling. Use only the trailers that apply:
```
Fixes:
Refs:
ADR:
RFC:
Design:
Co-authored-by:
Reviewed-by:
Signed-off-by:
BREAKING CHANGE:
```

View File

@@ -0,0 +1,170 @@
---
source_keys:
- conventional-commits-spec
- commitlint-config-conventional
---
# Conventional Commits Specification (v1.0.0)
Conventional Commits is a lightweight convention on top of commit messages that provides a set of rules for creating an explicit commit history. It enables automated tooling (CHANGELOG generation, semantic version bumping) and structured filtering.
## Message Format
```
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
```
Each section is separated by a blank line. The header is the only required part.
## Rules
| Element | Rule |
|---|---|
| `type` | Required. Lowercase noun. |
| `scope` | Optional. Noun in parentheses directly after type: `feat(api):`. |
| `description` | Required. Immediately follows `type/scope: `. Imperative mood, no trailing period. |
| `body` | Optional. Begins one blank line after description. Free-form prose, multiple paragraphs allowed. Lines max 100 characters. |
| `footer(s)` | Optional. Begins one blank line after body (or description). `<token>: <value>` format. Lines max 100 characters. |
| `BREAKING CHANGE` | Must be uppercase. Either a footer token or signalled by `!` before the colon. |
## Standard Types
The spec itself mandates only `feat` and `fix`. The 11-type set below is the de-facto standard from `@commitlint/config-conventional` (Angular commit message guidelines), not a spec requirement — but it is what this skill validates against.
### 11-type set (commitlint/config-conventional)
| Type | Meaning | SemVer impact | Appears in CHANGELOG |
|---|---|---|---|
| `feat` | New user-visible feature | MINOR | Yes |
| `fix` | Bug fix | PATCH | Yes |
| `perf` | Performance improvement, no API change | PATCH | Yes |
| `revert` | Reverts a previous commit | PATCH | Yes |
| `docs` | Documentation only | none | No |
| `style` | Formatting, whitespace — no logic change | none | No |
| `refactor` | Code restructuring — no feature or fix | none | No |
| `test` | Adding or fixing tests | none | No |
| `build` | Build system or external dependency changes | none | No |
| `ci` | CI configuration and scripts | none | No |
| `chore` | Anything not fitting above | none | No |
A `BREAKING CHANGE` footer or `!` on **any** type always triggers a MAJOR bump.
## Breaking Changes
Two equivalent notations:
**`!` in header** (preferred — visible in `git log --oneline`):
```
feat!: drop support for Node 6
feat(api)!: remove deprecated endpoint
```
**`BREAKING CHANGE` footer** (machine-readable body):
```
feat: allow config to extend other configs
BREAKING CHANGE: `extends` key now used for extending config files
```
**Both together** (most explicit):
```
feat!: drop support for Node 6
BREAKING CHANGE: use JavaScript features not available in Node 6.
```
Rules:
- `BREAKING CHANGE` must be all caps.
- `BREAKING-CHANGE` (hyphenated) is an accepted synonym.
- Any type can carry a breaking change, not just `feat`.
- The footer value must describe what broke.
## Footer Token Rules
```
<token>: <value>
<token> #<value> # for issue references
```
- Tokens use hyphens for word separation: `Reviewed-by`, `Co-authored-by`, `Refs`.
- Exception: `BREAKING CHANGE` (space allowed, uppercase).
- Multiple footers allowed, one per line.
- Blank line required before the footer block.
Valid footer examples:
```
Reviewed-by: Z
Refs: #123
Co-authored-by: Alice <alice@example.com>
BREAKING CHANGE: the `--format` flag now requires a value
```
## Examples
Minimal — no body, no footer:
```
docs: correct spelling of CHANGELOG
```
With scope:
```
feat(lang): add Polish language
```
Breaking change via `!`:
```
feat!: send an email to the customer when a product is shipped
```
Breaking change via footer:
```
feat: allow provided config object to extend other configs
BREAKING CHANGE: `extends` key in config file is now used for extending other config files
```
Multi-paragraph body with multiple footers:
```
fix: prevent racing of requests
Introduce a request id and a reference to latest request. Dismiss
incoming responses other than from latest request.
Remove timeouts which were used to mitigate the racing issue but are
obsolete now.
Reviewed-by: Z
Refs: #123
```
Revert:
```
revert: let us never again speak of the noodle incident
Refs: 676104e, a215868
```
## commitlint Constraints (config-conventional)
| Constraint | Value |
|---|---|
| Header max length | 100 characters |
| Subject must not end with `.` | enforced |
| Subject must be lowercase (not sentence-case or UPPER-CASE) | enforced |
| Body / footer line max length | 100 characters |
| Type must be one of the 11 standard types | error if not |
| Blank line before body | warning |
| Blank line before footer | warning |
## SemVer Mapping Summary
| Condition | SemVer bump |
|---|---|
| `fix`, `perf`, `revert` | PATCH |
| `feat` | MINOR |
| Any type with `BREAKING CHANGE` or `!` | MAJOR |
| All other types (`docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore`) | none |

View File

@@ -0,0 +1,40 @@
---
topic: commits
source_keys:
- conventional-commits-spec
- commitlint-config-conventional
- org-commit-conventions
- context7-git-htmldocs
---
# Research Sources for git:commits Skill
Sources extracted from the git plugin research phase. Only sources that directly informed this skill are listed; sibling skills (git:branches, git:history, git:remotes, etc.) have their own sources.md.
## conventional-commits-spec
- **Description:** Conventional Commits Specification (v1.0.0) — message format, types, breaking changes, footer rules
- **Research doc:** plugins/git/docs/research/docs/git/commits.md § "Conventional Commits Specification (v1.0.0)"
- **Contributing files:** SKILL.md, references/conventional-commits-spec.md
- **Status:** extracted
## commitlint-config-conventional
- **Description:** commitlint config-conventional preset — validation constraints (max 100 chars header, no trailing periods, lowercase type, 11-type set enforcement)
- **Research doc:** plugins/git/docs/research/docs/git/commits.md § "commitlint Constraints (`config-conventional`)"
- **Contributing files:** SKILL.md, references/conventional-commits-spec.md
- **Status:** extracted
## org-commit-conventions
- **Description:** Organization commit message body template and git conventions (atomic commits, no `--no-verify`, no force-push main/master, `rtk git` wrapper) — content fully embedded in this skill; the org's `core/instructions/git.md` and `core/instructions/commits.md` are provenance only and are not a live dependency
- **Research doc:** core/instructions/commits.md, core/instructions/git.md (org convention, not part of the plugin's research corpus)
- **Contributing files:** SKILL.md, references/commit-template.md
- **Status:** extracted
## context7-git-htmldocs
- **Description:** Official Git HTML documentation — `git commit --squash`/`--fixup` and `git rebase --autosquash` flag semantics
- **Research doc:** plugins/git/docs/research/docs/git/cli-reference.md
- **Contributing files:** SKILL.md
- **Status:** extracted

View File

@@ -0,0 +1,24 @@
# git-history
Inspect git history — log queries, bisect, and locating problematic commits.
## What it does
This skill handles history inspection within the git workflow suite. It queries logs with pickaxe/line-range/custom formats, runs bisect to find bug-introducing commits, and locates commits for downstream cherry-picking or reverting. It returns structured results for agent composition. Rebase, squash, fixup, and other history-rewriting operations are owned by git-commits, not this skill.
## Usage
```
/git-history
```
Describe your history task: search logs, bisect for a regression, or locate a specific commit. The skill will query history and return structured results.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/git-log-format.md` | Full log format placeholders, diff-filter letters, `-L` syntax, ancestry filters, diff output-control flags |
| `references/sources.md` | Research sources and provenance |
| `references/README.md` | Index of the references directory |

View File

@@ -0,0 +1,96 @@
---
name: git-history
description: >
Inspect git history: query logs with pickaxe, line-range, or custom formats; find bug origins via bisect; locate problematic commits for cherry-picking or reverting. Use when investigating history, tracing when a change happened, or finding the commit that broke something. Return structured results for downstream agents. Do not use for authoring or formatting commit messages, or executing rebase/squash/fixup operations — use git-commits for that.
metadata:
category: git
source_keys:
- git-scm-bisect-docs
- git-scm-log-docs
- git-scm-diff-docs
allowed-tools: Bash
---
## Gotchas
- **Pickaxe searches (`-S` vs `-G`)**: `-S"string"` finds commits where string count changed; `-G"regex"` finds any line matching regex in diffs. They're not equivalent: a line replaced (one removal + one addition) matches `-G` but not `-S` if count is unchanged.
- **`--follow` only works for single files**: it traces renames but fails with multiple paths or directory globs. Use `git log -- <single-file>` or query without `--follow`.
- **Bisect with skips**: if bisect cannot pinpoint a commit because the culprit is adjacent to skipped commits, it reports "cannot find exact culprit" and lists candidates. This is not a failure — it's as precise as the skip range allows.
- **Interactive rebase is non-recoverable on mistake**: there's no undo once `rebase -i` starts. Suggest `git reflog` to recover if the user realizes mid-way they selected the wrong commits.
- **`-L` (line-range history) requires exact line numbers or regex patterns**: off-by-one errors omit the target range. Test the range with `git log -L` before offering it to users.
## Query Logs and Locate Commits
Default to `git log --oneline` for quick inspection. For deeper queries:
- **Find when a string appeared or disappeared**: Use `git log -S"string"` (count-sensitive, finds adds/removes). If you need any mention of the string in diffs, use `git log -G"regex"` instead. Add `--pickaxe-regex` to treat the `-S` string as a POSIX ERE, and `--pickaxe-all` to show every changed file in a matching changeset, not just the matching ones. Binary files are searched by `-S`; `-G` ignores them unless `--text` is also supplied.
- **Trace changes to a specific line or function**: Use `git log -L <start>,<end>:<file>` or `git log -L :<function>:<file>` (requires function name heuristic). This shows the evolution of that range across all commits.
- **Filter by change type**: Use `git log --diff-filter=<type>` (A=added, M=modified, D=deleted, R=renamed) to narrow to specific file operations.
- **Mainline-only history through merges**: Use `--first-parent` to follow only the integration branch and skip merged-in side-branch commits; combine with `--merges`/`--no-merges` or `--ancestry-path`/`--min-parents`/`--max-parents` for other ancestry-graph filtering — see `references/git-log-format.md` for the full set.
- **Custom format for structured output**: Construct format string with `%h` (hash), `%s` (subject), `%an` (author), `%ar` (relative date), `%b` (body). Example: `git log --format="%h | %s | %an (%ar)"`.
- **File-specific history with renames**: Use `git log --follow -- <file>` (single file only). Without `--follow`, log stops at the rename boundary.
## Bisect to Find Blame Commit
Use bisect when hunting for the commit that introduced a bug or behaviour change. Binary search reduces iterations from O(N) to O(log N).
**Basic manual flow:**
```bash
git bisect start
git bisect bad [HEAD] # mark current (or specified) as broken
git bisect good <commit> # mark known-good baseline
# Git checks out midpoint; test it manually
git bisect good # if test passes
git bisect bad # if test fails
# Repeat until git reports "X is the first bad commit"
git bisect reset # return to original HEAD
```
**Automated with `git bisect run`:** if a test command exists, use `git bisect run <cmd>`. Git interprets the exit code: `0`=good, `1-124`=bad, `125`=skip (build broken), `126-127`=POSIX shell errors treated as bad, `128+`=**aborts the bisect session entirely** (not treated as bad — a crashed test script can silently end the search).
**With skip:** if a commit is untestable (broken build), use `git bisect skip` to exclude it without manually deciding good/bad. If the first-bad is adjacent to skips, bisect reports it cannot pinpoint but lists candidates.
**Undoing a wrong good/bad call:** `git bisect log` prints the session's decision history; save it (`git bisect log > bisect.log`), edit out the mistaken entry, then `git bisect reset && git bisect replay bisect.log` to resume from the corrected log instead of restarting the whole search.
**Narrowing and speeding up the search:** `git bisect start HEAD v1.2 -- src/` limits bisection to a path, cutting the number of trials. `--no-checkout` updates the `BISECT_HEAD` ref instead of checking out a working tree (useful for tests that don't need one; automatic in bare repos). `--first-parent` follows only first parents at merges, finding the integration commit that introduced a regression while ignoring broken side branches.
**Inspecting remaining candidates visually:** `git bisect visualize` (alias `view`) opens the suspects in gitk; add `--stat` or `-p` to show diffstat or full patches instead. Falls back to `git log` when no graphical display is detected.
**For non-regression hunts:** use `git bisect start --term-new <new> --term-old <old>` to search for a property change instead of a bug (e.g., performance regression). Then use the custom terms instead of `good`/`bad`.
For rebase execution (interactive rebase, squash/fixup/reword, conflict handling) see git-commits — it owns history-rewriting operations. This skill only locates commits and reports on history; it does not execute rebases.
## Find and Manipulate Problematic Commits
Once a commit is identified (via log query or bisect), offer cherry-pick or revert. This section is general git knowledge, not sourced from `history-inspection.md` — `git-branches`'s SKILL.md explicitly delegates cherry-pick/revert here (see its Merging section), which is why this skill carries them rather than treating them as out of scope:
- **Cherry-pick**: `git cherry-pick <commit>` copies a commit's changes onto current HEAD. Use when backporting fixes to other branches.
- **Revert**: `git revert <commit>` creates a new commit that undoes the changes. Use when un-applying a merged commit without rewriting history.
- **Blame for context**: `git blame <file>` shows which commit last changed each line. Use to trace a specific line back to its introducing commit.
## Inspect Diffs
Diff-output tuning is in scope too: `--stat` for a diffstat summary, `--word-diff` for word-level (not line-level) changes, and whitespace flags (`-w`, `--ignore-blank-lines`) to suppress noise from reformatting. See `references/git-log-format.md` for the full flag set.
## Return Results Structured
For agent consumption, return:
- **Commit SHA** (full or abbreviated as appropriate)
- **Subject line** (from `%s`)
- **Author and date** (from `%an` and `%ar`)
- **Action taken or recommended** (e.g., "Found via bisect", "Offer cherry-pick to main", "Rebase conflicts detected")
Example for agent:
```
Found first bad commit: abc1234
Subject: fix null pointer in parser
Author: Alice (2 weeks ago)
Recommendation: Backport to release branch via cherry-pick
```
## Reference
For the full log format placeholder catalogue, named format presets, `--diff-filter` letters, `-L` range syntax, ancestry filters, and `git diff` output-control flags, read `references/git-log-format.md`.

View File

@@ -0,0 +1,15 @@
---
source_keys:
- git-scm-bisect-docs
- git-scm-log-docs
- git-scm-diff-docs
---
# References
This directory contains provenance metadata and research sources for the `git-history` skill.
## Files
- `sources.md` — Extracted research sources and their contributing documents
- `git-log-format.md` — Full `git log` format placeholder catalogue, named format presets, `--diff-filter` letters, `-L` line-range syntax, ancestry filters, and `git diff` output-control flags

View File

@@ -0,0 +1,232 @@
---
topic: git-log-format
source_keys:
- git-scm-log-docs
- git-scm-diff-docs
---
## Named Format Presets (`--format` / `--pretty`)
| Name | Output |
|---|---|
| `oneline` | `<hash> <title>` |
| `short` | hash, author, title |
| `medium` | hash, author, date, full message (default) |
| `full` | adds committer |
| `fuller` | separate author/committer dates |
| `reference` | `<abbrev> (<title>, <date>)` — for use in commit messages |
| `email` | RFC 2822 email format |
| `raw` | full object as stored in the object database |
| `format:<str>` | custom template with placeholders |
## Custom Format Placeholders
**Commit identity:**
| Placeholder | Meaning |
|---|---|
| `%H` | full commit hash |
| `%h` | abbreviated commit hash |
| `%T` | tree hash |
| `%t` | abbreviated tree hash |
| `%P` | full parent hashes |
| `%p` | abbreviated parent hashes |
**Author:**
| Placeholder | Meaning |
|---|---|
| `%an` | author name |
| `%aN` | author name (mailmap-resolved) |
| `%ae` | author email |
| `%aE` | author email (mailmap-resolved) |
| `%ad` | author date (respects `--date=`) |
| `%ar` | author date, relative |
| `%at` | author date, UNIX timestamp |
| `%ai` | author date, ISO 8601-like |
| `%aI` | author date, strict ISO 8601 |
| `%as` | author date, short (YYYY-MM-DD) |
**Committer:**
| Placeholder | Meaning |
|---|---|
| `%cn` | committer name |
| `%ce` | committer email |
| `%cd` | committer date (respects `--date=`) |
| `%cr` | committer date, relative |
| `%ct` | committer date, UNIX timestamp |
| `%ci` | committer date, ISO 8601-like |
| `%cs` | committer date, short |
**Message:**
| Placeholder | Meaning |
|---|---|
| `%s` | subject (first line) |
| `%f` | sanitized subject (filename-safe) |
| `%b` | body (everything after blank line following subject) |
| `%B` | raw body (subject + body) |
| `%N` | commit notes |
**Refs and decorations:**
| Placeholder | Meaning |
|---|---|
| `%d` | ref names (like `--decorate`) |
| `%D` | ref names without surrounding parentheses |
| `%S` | ref name by which commit was reached (requires `--source`) |
| `%(decorate[:opts])` | custom decorated refs; options: `prefix=`, `suffix=`, `separator=`, `pointer=`, `tag=` |
| `%(describe[:opts])` | like `git describe`; options: `tags=`, `abbrev=`, `match=`, `exclude=` |
**GPG signature:**
| Placeholder | Meaning |
|---|---|
| `%G?` | status: `G`=good, `B`=bad, `U`=unknown, `X`=expired, `R`=revoked, `N`=no signature |
| `%GS` | signer name |
| `%GK` | signing key ID |
**Trailers:**
```
%(trailers[:key=<k>][,only][,separator=<s>][,unfold][,keyonly][,valueonly])
```
**Formatting / color:**
| Placeholder | Meaning |
|---|---|
| `%n` | newline |
| `%%` | literal `%` |
| `%Cred` / `%Cgreen` / `%Cblue` / `%Creset` | terminal colors |
| `%C(<spec>)` | color per git-config spec |
| `%<(<n>[,trunc])` | right-pad field to width n |
| `%>(<n>)` | left-pad to width |
**Reflog** (requires `-g` / `--walk-reflogs`):
| Placeholder | Meaning |
|---|---|
| `%gD` | reflog selector (e.g. `refs/stash@{1}`) |
| `%gd` | shortened reflog selector |
| `%gs` | reflog subject |
## Pickaxe Search: -S and -G
**`-S<string>`** — finds commits where the **count** of `<string>` changed (i.e. the string was added or removed net). Does not match commits where the string merely appears in a diff hunk without a count change.
```bash
git log -S"my_function"
git log -S"my_function" --pickaxe-regex # treat as POSIX ERE
git log -S"my_function" --pickaxe-all # show all files in matching changesets
```
**`-G<regex>`** — finds commits where any added or removed **line** in the patch matches `<regex>`. Broader than `-S`: matches whenever the pattern appears in diff text regardless of count.
```bash
git log -G"frotz\(nitfol"
```
**Critical distinction:** given a diff that removes one occurrence of `foo` and adds one occurrence of `foo` (net change = 0):
- `-S"foo"` — does **not** match (count unchanged)
- `-G"foo"` — **matches** (pattern appears in patch text)
Binary files are searched by `-S`; ignored by `-G` unless `--text` is supplied.
## --diff-filter (full table)
Selects commits (in `git log`) or files (in `git diff`) by change type:
| Letter | Meaning |
|---|---|
| `A` | Added |
| `C` | Copied |
| `D` | Deleted |
| `M` | Modified |
| `R` | Renamed |
| `T` | Type changed (regular file ↔ symlink ↔ submodule) |
| `U` | Unmerged (conflict) |
| `X` | Unknown (indicates a git bug) |
| `B` | Pairing broken |
Lowercase letters **exclude** that type:
```bash
git log --diff-filter=ad # exclude added and deleted files
git log --diff-filter=M # only show commits with modified files
```
`C` and `R` only appear when copy/rename detection is enabled (`-C`, `-M` flags or `diff.renames` config).
## -L — Line Range History (full syntax)
Traces the evolution of a specific range of lines or a named function through commits. Implies `--patch`.
```bash
git log -L 10,20:file.txt
git log -L /start_pattern/,/end_pattern/:file.txt
git log -L :myfunction:src/app.c
git log -L /init/,+15:config.py # 15 lines after first match of /init/
```
Range formats:
| Format | Meaning |
|---|---|
| `<n>` | Absolute line number (1-based) |
| `/<regex>/` | First line matching regex from previous range end |
| `^/<regex>/` | First line matching regex from file start |
| `+<n>` / `-<n>` | Offset relative to `<start>` (end position only) |
Limitations: incompatible with `--raw`, `--numstat`, `--shortstat`, `--name-only`, `--name-status`, `--check`. Cannot use pathspec limiters alongside `-L`.
## Graph and Ancestry Filters
```bash
git log --first-parent # at merges, follow only first parent (mainline evolution)
git log --merges # only merge commits (≥2 parents); equivalent to --min-parents=2
git log --no-merges # only non-merge commits; equivalent to --max-parents=1
git log --ancestry-path D..M # only commits actually on the path from D to M
git log --min-parents=<n> # include only commits with ≥ n parents
git log --max-parents=<n> # include only commits with ≤ n parents
```
`--ancestry-path` is significant: without it, `D..M` includes all commits reachable from M but not D — including side branches that merged into the path. With it, only commits directly between D and M are shown.
## git diff — Output Control
### --stat
```bash
git diff --stat # diffstat: file names + ± bar
git diff --stat=<width>,<name-width>,<count>
git diff --compact-summary # alongside --stat: shows new/gone, +x/-x (executable), +l (symlink)
git diff --numstat # machine-readable: <added>\t<deleted>\t<path>; - for binary
```
### --name-only / --name-status
```bash
git diff --name-only # only filenames, one per line
git diff --name-status # status letter + filename per line
```
`--name-status` uses the same status letters as `--diff-filter`.
### --word-diff
```bash
git diff --word-diff # inline word-level diff with [-removed-] {+added+} markers
git diff --word-diff=color # color only, no markers
git diff --word-diff=porcelain # machine-readable: +/- prefixed lines, ~ for newlines
git diff --word-diff-regex=<re> # define what counts as a "word"
```
### Whitespace Flags
| Flag | Effect |
|---|---|
| `-b` / `--ignore-space-change` | Treat any run of whitespace as equivalent; ignore trailing whitespace |
| `-w` / `--ignore-all-space` | Ignore all whitespace completely |
| `--ignore-space-at-eol` | Ignore whitespace at end-of-line only |
| `--ignore-blank-lines` | Ignore changes consisting entirely of blank lines |
| `-I<regex>` / `--ignore-matching-lines=<re>` | Ignore changes where all changed lines match regex |

View File

@@ -0,0 +1,31 @@
---
topic: history-inspection
source_keys:
- git-scm-bisect-docs
- git-scm-log-docs
- git-scm-diff-docs
---
## git-scm-bisect-docs
Git bisect documentation covering binary search through commit history to find the commit that introduced a bug. Includes manual flow, automated mode with exit codes, skip patterns, and visualization options.
- **Research doc:** plugins/git/docs/research/docs/git/history-inspection.md
- **Doc heading:** `## git bisect`
- **Contributing files:** SKILL.md
## git-scm-log-docs
Git log documentation covering format presets, custom format placeholders (commit identity, author, committer, message, refs, GPG signature), pickaxe search (`-S` and `-G`), `--follow` for file renames, `--diff-filter`, and line-range history (`-L`).
- **Research doc:** plugins/git/docs/research/docs/git/history-inspection.md
- **Doc heading:** `## git log — Format and Filtering`
- **Contributing files:** SKILL.md, references/git-log-format.md
## git-scm-diff-docs
Git diff documentation covering output control (--stat, --name-only, --name-status, --word-diff) and whitespace handling flags.
- **Research doc:** plugins/git/docs/research/docs/git/history-inspection.md
- **Doc heading:** `## git diff — Output Control`
- **Contributing files:** references/git-log-format.md

View File

@@ -0,0 +1,24 @@
# git-remotes
Manage git remote repositories — add/remove/configure remotes, push/pull with safety checks, fetch with pruning, and multi-remote workflows.
## What it does
This skill handles remote operations within the git workflow suite. It manages remote configuration (add, remove, rename), fetch operations with pruning, push operations with force-push safety (`--force-with-lease --force-if-includes`), and pull strategies (fast-forward, rebase, merge). It returns structured results suitable for agent composition.
## Usage
```
/git-remotes
```
Describe your remote operation: add a remote, push, pull, fetch, or configure tracking. The skill will handle the operation with appropriate safety checks and return results.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/README.md` | Describes the references directory contents |
| `references/remotes.md` | Full `set-url` variants, shallow-clone/fetch options, force-push mitigation detail, and pull config precedence |
| `references/sources.md` | Research sources and provenance |

View File

@@ -0,0 +1,123 @@
---
name: git-remotes
description: >
Manage git remote repositories — add/remove/configure remotes, push/pull with safety checks,
handle fetch patterns and tracking branch updates, support multi-remote workflows.
Use when automating remote operations, pushing with force-push safety, fetching with pruning,
pulling with divergence resolution, or managing multi-remote tracking. Include indirect triggers:
any git operation that touches a remote, even if the user doesn't explicitly name the remote.
Do not use when working with local git history, commits, branches, or staging — use git-history
or git-branches instead.
metadata:
category: git-workflow
source_keys:
- git-scm-remote-docs
- git-scm-fetch-docs
- git-scm-push-docs
- git-scm-pull-docs
- context7-git-htmldocs
---
## Gotchas
- **Never force-push `main` or `master`, under any circumstances** — this is a hard refusal, not a `confirm: true` gate. If a force-push targets one of these branches, decline and explain why, regardless of how the request is confirmed.
- **Force-push to any other branch requires explicit confirmation** — never execute `git push --force` or `git push -f` without user/agent approval. Always ask or require `confirm: true` flag first.
- **`--force-with-lease` alone is not safe** — background processes (IDE plugins, cron jobs) that run `git fetch` silently defeat the protection. Always combine with `--force-if-includes` or use explicit SHA form `--force-with-lease=<ref>:<sha>`.
- **Prune doesn't touch tags by default** — `git fetch --prune` leaves orphaned tags. Use `git fetch --prune --prune-tags` or configure `fetch.pruneTags true` globally.
- **Pull with rebase rewrites history** — only safe for unpublished work. Rebasing already-pushed commits breaks everyone downstream. Check what's been pushed before rebasing.
- **`git remote show` requires network access** — use `-n` flag for cached data if working offline. `git remote -v` lists URLs without network queries.
- **Pull behavior defaults shift between Git versions** — older versions default to merge, newer versions to `--ff-only`. Always set `pull.ff only` explicitly for deterministic behavior.
## Operations
### Remote Management
Use these to configure which remotes you push to and pull from:
- **Add a remote**: `git remote add <name> <url>` or `git remote add -f <name> <url>` to fetch immediately
- **Remove a remote**: `git remote remove <name>` (deletes remote + all tracking refs + config)
- **Rename a remote**: `git remote rename <old> <new>`
- **Inspect remotes**: `git remote -v` (show URLs) or `git remote show <name>` (live tracking status, requires network)
- **Set-url separately for fetch vs. push**: `git remote set-url --push <name> <url>` changes only where pushes go — but fetch and push URLs must still reference the same repository. For genuine fetch-from-A / push-to-B workflows, use two separate named remotes instead; `--push` cannot do this. Full `set-url` variants (regex-targeted replace, `--add`, `--delete`): `references/remotes.md`.
- **Remove a stale URL**: `git remote set-url --delete <name> <regex>`
- **Inspect effective URLs**: `git remote get-url <name>` (shows URL after `insteadOf` rewrites) or `git remote get-url --push --all <name>` (all push URLs)
- **Track only one branch**: `git remote add -t <branch> <name> <url>` (repeatable), or suppress tag import entirely with `git remote add --no-tags <name> <url>`
- **Mirror a remote**: `git remote add --mirror=fetch <name> <url>` mirrors all refs locally (bare repos only); `--mirror=push` makes every push behave like `--mirror`
- **Prune stale tracking refs without fetching**: `git remote prune <name>` (add `--dry-run` to preview first)
- **Set the remote's default branch pointer**: `git remote set-head <name> -a` (auto-detect, requires a prior fetch), `git remote set-head <name> <branch>` (explicit), or `git remote set-head <name> -d` (delete `refs/remotes/<name>/HEAD`)
### Fetch Operations
Use these to update your tracking branches without touching your local branches:
- **Fetch from one remote**: `git fetch <remote>` — fetches all branches
- **Fetch one branch only**: `git fetch <remote> <branch>` — stores the result in `FETCH_HEAD`, not a tracking ref
- **Fetch from all remotes**: `git fetch --all` with optional `--prune` to clean up stale tracking refs
- **Prune properly**: Use `git fetch --all --prune --prune-tags` to clean both branches and tags
- **Configure auto-prune**: Set `git config --global fetch.prune true` to auto-prune on every fetch across all remotes (or `remote.<name>.prune` to scope it to one remote)
- **Shallow clones**: `--depth=<n>` to deepen or create a shallow clone, `--unshallow` to convert to full history, `--update-shallow` to allow the shallow boundary to move. Details and the default fetch refspec: `references/remotes.md`.
Fetch never modifies your local branches — it only updates remote-tracking branches (`refs/remotes/origin/*`).
### Push Operations
Use these to send your commits upstream. Default: safe push to same-named branch on the remote.
- **Basic push**: `git push <remote> <branch>` — pushes to same-named remote branch
- **Set upstream**: `git push -u <remote> <branch>` — push and configure this branch to track the remote
- **Multi-remote push**: `git push origin develop` and `git push staging develop` sequentially, or use `git remote set-url --add <name> <url>` to push to multiple remotes with one command
- **Force-push safety**: Always use `git push --force-with-lease --force-if-includes <remote> <branch>` over bare `--force`. Require explicit confirmation first — and never for `main`/`master` (see Gotchas). `--force-if-includes` is a no-op without `--force-with-lease`. If background tools (IDE, cron) auto-fetch and could poison the lease check, use a dedicated push-only remote instead — see `references/remotes.md`.
- **Server-side enforcement**: `receive.denyDeletes`, `receive.denyDeleteCurrent`, and `receive.denyNonFastForwards` are enforced on the remote regardless of local flags — a hardened server rejects the push even with `--force`.
- **Delete remote branch**: `git push <remote> --delete <branch>` (not `:<branch>` syntax; clearer and cleaner)
- **Push everything**: `git push --all` (all local branches) or `git push --tags` (all tags)
- **Push a single tag**: `git push origin <tag>`
- **Delete remote branches with no local counterpart**: `git push --prune origin 'refs/heads/*:refs/heads/*'`
- **Force only part of a multi-ref push**: prefix the one refspec that needs it with `+`, e.g. `git push origin +main develop` forces `main` while safe-pushing `develop`
Refspec syntax is `[+]<src>[:<dst>]`:
| Pattern | Meaning |
|---|---|
| `<branch>` | Push to same-named remote branch |
| `<src>:<dst>` | Push `<src>` local ref to `<dst>` remote ref |
| `+<src>:<dst>` | Force this refspec (non-fast-forward allowed) |
| `:<branch>` | Delete remote `<branch>` |
| `refs/heads/*:refs/heads/*` | Glob: push all matching branches |
| `^refs/heads/dev-*` | Negative: exclude matching refs |
| `tag <name>` | Sugar for `refs/tags/<name>:refs/tags/<name>` |
### Pull Operations
Use these to fetch and integrate remote changes. Default strategy: `--ff-only` (fail if diverged, forcing a conscious choice).
- **Pull with fast-forward only**: `git pull --ff-only` (recommended default — fails if you've diverged, forcing a rebase/merge decision)
- **Pull with rebase**: `git pull --rebase` (replays your unpublished commits on top; linear history, but rewrites SHAs — only safe for unpublished work)
- **Pull with merge**: `git pull --no-rebase` (three-way merge commit; preserves original commits, non-linear)
- **Pull with rebase, preserving merges**: `git pull --rebase=merges` (like `--rebase`, but keeps intentional local merge commits during replay)
- **Pull without integrating**: `git pull --squash` collapses incoming commits into staged changes without committing — you write the commit message
- **Set pull strategy globally**: `git config pull.ff only` (or `pull.rebase true`; respects branch-specific overrides via `branch.<name>.rebase`). Full precedence order (CLI flag > `pull.rebase` > `branch.<name>.rebase` > `branch.autoSetupRebase`): `references/remotes.md`.
- **Check before rebasing**: Always verify your commits haven't been pushed before using `--rebase`. Rebasing published commits breaks everyone downstream.
- **Merge strategy default**: Git 2.34+ defaults to the `ort` merge strategy (`recursive` is now just an alias for it). Strategy options like `-X ours`, `-X theirs`, `-X ignore-space-change` still pass through unchanged.
- **Submodules on pull**: `--recurse-submodules` only fetches submodules that are already checked out — newly added submodules are not initialized automatically. Use the `git-submodules` skill to initialize new ones.
If pull diverges and you haven't set a strategy, the operation fails — this is good, forces a conscious choice. Never auto-merge diverged branches without asking.
### Return Format (for agents)
Return structured output:
```json
{
"success": true,
"operation": "push",
"remote": "origin",
"branch": "main",
"output": "...",
"warnings": ["force-with-lease not confirmed"],
"recommendations": ["set pull.ff=only globally"]
}
```
On failure, include `error` field with root cause and recovery suggestion.

View File

@@ -0,0 +1,17 @@
---
source_keys:
- git-scm-remote-docs
- git-scm-fetch-docs
- git-scm-push-docs
- git-scm-pull-docs
- context7-git-htmldocs
---
# References
This directory contains provenance metadata and research sources for the `git-remotes` skill.
## Files
- `sources.md` — Extracted research sources and their contributing documents
- `remotes.md` — Full `set-url` variants, shallow-clone/fetch options, default fetch refspec, force-push mitigation detail, server-side deny policies, and pull config precedence

View File

@@ -0,0 +1,82 @@
---
topic: remotes
source_keys:
- git-scm-remote-docs
- git-scm-fetch-docs
- git-scm-push-docs
- git-scm-pull-docs
---
## `set-url` — full form
```bash
git remote set-url <name> <newurl> # replace the first fetch URL
git remote set-url <name> <newurl> <oldurl-regex> # replace only the URL matching regex
git remote set-url --push <name> <url> # change push URL only (must point at same repo)
git remote set-url --add <name> <url> # add an extra push URL (push to multiple remotes)
git remote set-url --delete <name> <regex> # remove URLs matching regex
```
`--push` changes only where pushes go — fetch and push URLs must still reference the same repository. For genuine fetch-from-A / push-to-B workflows, use two separate named remotes instead.
## Shallow clones and partial fetch
```bash
git fetch <remote> <branch> # fetch one branch only, stored in FETCH_HEAD (not a local/tracking ref)
git fetch --depth=<n> # deepen history, or create a shallow clone
git fetch --unshallow # convert a shallow clone to full history
git fetch --update-shallow # allow the fetch to update the shallow boundary
git fetch --refmap='' <remote> <branch> # fetch without updating any tracking ref (FETCH_HEAD only)
```
## Default fetch refspec
The default fetch refspec is `+refs/heads/*:refs/remotes/<name>/*`. The leading `+` forces the update — remote-tracking branches always mirror the remote exactly and provide no protection for local history. Fetch never touches your local branches, only remote-tracking refs.
## Force-push safety — full detail
`--force-with-lease` rejects the push if the remote ref moved since your last fetch. Three forms:
| Form | What it protects |
|---|---|
| `--force-with-lease` (bare) | All refs being pushed, checked against your remote-tracking branch |
| `--force-with-lease=<refname>` | Named ref only |
| `--force-with-lease=<refname>:<sha>` | Named ref must be at exact SHA — most stable |
**Caveat with the bare form:** any background process that runs `git fetch` (IDE plugin, cron job, editor auto-fetch) updates your remote-tracking branch, which can make the lease check pass even though someone else pushed in between. The protection is silently defeated.
Two mitigations:
```bash
# Option 1 — dedicated push-only remote: background tools fetch `origin`, you push
# through a separate remote that nothing else touches, so its tracking ref can't be
# poisoned by an unrelated fetch.
git remote add origin-push $(git config remote.origin.url)
git push --force-with-lease origin-push
# Option 2 — explicit SHA via a local tag, unaffected by tracking-branch state
git fetch
git tag base master
git rebase -i master
git push --force-with-lease=master:base master:master
```
`--force-if-includes` adds a second check on top of bare `--force-with-lease`: it verifies the remote-tracking tip actually appears in your local branch's reflog, i.e. you genuinely integrated it before rewriting. It is a no-op without `--force-with-lease`, and has no effect when the `--force-with-lease=<ref>:<sha>` form is used (that form already pins an exact SHA).
Safest combination: `git push --force-with-lease --force-if-includes origin`.
Remote-side policies (`receive.denyDeletes`, `receive.denyDeleteCurrent`, `receive.denyNonFastForwards`) are enforced server-side regardless of any local flag — a server configured this way rejects the push even with `--force`.
## Pull config precedence
Highest wins:
1. Command-line flag (`--ff-only` / `--rebase` / `--no-rebase`)
2. `pull.rebase` config (global or local)
3. `branch.<name>.rebase` (branch-specific override)
4. `branch.autoSetupRebase` (set automatically when the tracking branch was created)
```bash
git config --global pull.rebase true
git config branch.develop.rebase false # develop always merges, regardless of the global default
```

View File

@@ -0,0 +1,71 @@
---
# Research sources referenced by this skill
# Each entry documents where the skill's guidance came from.
---
## git-scm-remote-docs
**Description:** Git SCM official documentation for `git remote` command — remote configuration, add/remove/rename, URL management, inspection, and housekeeping.
**Source:** https://git-scm.com/docs/git-remote
- **Research doc:** plugins/git/docs/research/docs/git/remotes.md → `## Remote Management (`git remote`)`
**Contributing files:**
- SKILL.md (Remote Management section)
- references/remotes.md (`set-url` full form)
---
## git-scm-fetch-docs
**Description:** Git SCM official documentation for `git fetch` command — fetching from remotes, tracking branch updates, pruning stale refs, shallow clones, and refspecs.
**Source:** https://git-scm.com/docs/git-fetch
- **Research doc:** plugins/git/docs/research/docs/git/remotes.md → `## Fetching (`git fetch`)`
**Contributing files:**
- SKILL.md (Fetch Operations section, Gotchas)
- references/remotes.md (shallow clones, default fetch refspec)
---
## git-scm-push-docs
**Description:** Git SCM official documentation for `git push` command — pushing branches, tags, force-push safety (--force-with-lease, --force-if-includes), refspecs, and multi-remote workflows.
**Source:** https://git-scm.com/docs/git-push
- **Research doc:** plugins/git/docs/research/docs/git/remotes.md → `## Pushing (`git push`)`
**Contributing files:**
- SKILL.md (Push Operations section, Gotchas)
- references/remotes.md (force-push safety full detail, server-side deny policies)
---
## git-scm-pull-docs
**Description:** Git SCM official documentation for `git pull` command — fetch + merge/rebase strategies, divergence resolution (--ff-only, --rebase, merge), config precedence, and pull-specific gotchas.
**Source:** https://git-scm.com/docs/git-pull
- **Research doc:** plugins/git/docs/research/docs/git/remotes.md → `## Pulling (`git pull`)`
**Contributing files:**
- SKILL.md (Pull Operations section, Gotchas)
- references/remotes.md (pull config precedence)
---
## context7-git-htmldocs
**Description:** Context7 MCP library providing current Git documentation and API reference — used for validation of modern Git syntax, behavior, and config semantics. This is a blanket cross-cutting reference and does not map to a single heading in the research doc; it informed terminology and syntax checks across all sections.
**Source:** Context7 MCP / Git library
- **Research doc:** plugins/git/docs/research/docs/git/remotes.md (cross-cutting — no dedicated section)
**Contributing files:**
- SKILL.md (all sections)

View File

@@ -0,0 +1,24 @@
# git-submodules
Initialize, clone, update, and manage git submodules for multi-repository projects.
## What it does
This skill handles submodule operations within the git workflow suite. It initializes submodules, clones repositories with nested submodule dependencies, updates submodule pinning, and manages version control across multi-repo projects. The skill provides clean workflows for projects with complex dependency structures and returns structured results suitable for agent composition.
## Usage
```
/git-submodules
```
Describe your submodule task: initialize, clone, update, or manage versions. The skill will handle the operation and return structured results (operation, status, per-submodule details, conflicts, and a recovery `next_step` when applicable) suitable for agent composition.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/README.md` | Describes contents of references/ |
| `references/submodules.md` | Deep-dive reference: full flag tables, workflow patterns, safe-removal sequence, `absorbgitdirs`, `foreach` variables |
| `references/sources.md` | Research sources and provenance |

View File

@@ -0,0 +1,91 @@
---
name: git-submodules
description: >
Use when managing Git submodules: add dependencies as submodules, initialize and update nested repositories, sync URLs, inspect status (including detached HEAD and divergence), and safely remove submodules. Handles multi-repo projects with pinning, parallel operations, and recursive traversal. Use for both initial setup and ongoing maintenance workflows, even if the user doesn't explicitly say "submodule". Do not use for general git operations outside of submodule management.
metadata:
category: git
source_keys:
- git-scm-submodule-docs
---
## Concept
A submodule is a full Git repository embedded as a subdirectory inside a parent repository (the superproject). The superproject doesn't store the submodule's files — it stores a pointer to a specific commit SHA in the submodule's own history, and the two repos keep fully independent commit histories.
Two files govern a submodule, and they serve different audiences:
- **`.gitmodules`** — version-controlled, shared with collaborators. Defines each submodule's name, path, and canonical URL.
- **`.git/config`** — local only, populated by `git submodule init`. This is where local URL overrides live (e.g. a private mirror) — they never propagate to other clones.
The submodule's own `.git` directory lives at `.git/modules/<name>/` in the superproject, linked to the submodule's working tree via a `.git` pointer file. After `git submodule update`, the working tree normally ends up in **detached HEAD state** — see Gotchas.
## Gotchas
- **Detached HEAD by default.** `git submodule update` checks out a specific commit, not a branch. Work on a branch first, then update the pointer in the superproject. Commits made in detached state are invisible until pinned.
- **Two pushes required, in order.** Always commit and push the submodule first, then update and push the superproject's pointer. The superproject only stores a commit SHA — if that SHA isn't reachable on the submodule's remote yet, `git submodule update` fails for anyone who pulls the superproject before the submodule push lands.
- **`--recursive` is not default.** Most commands operate one level deep. Pass `--recursive` explicitly for nested submodules.
- **`.git/modules/` persists after `git rm`.** Manual cleanup is needed: `rm -rf .git/modules/<name>/`.
- **Detached HEAD detection.** Status prefix `+` means the checked-out commit differs from the superproject's recorded commit — normal after `update --remote`, but should be re-pinned before committing.
- **Relative URLs resolve against the remote, not the filesystem.** A `../foo.git` entry in `.gitmodules` is relative to the superproject's default remote URL.
- **Custom `update` commands are security-gated.** A `.gitmodules` entry of `update = !some-command` is never copied to `.git/config` by `git submodule init` — this stops a clone from silently executing arbitrary code.
## Conventions
- **Use `rtk git` for parent-repo operations.** Drop into the submodule directory only for submodule-specific git commands (committing/pushing inside the submodule itself) — mixing the two from the wrong working directory targets the wrong repo's history.
- **Check for a dirty submodule before committing the parent pointer.** After adding or updating a submodule, run `git status` in both the parent and the submodule. A `-dirty` suffix means the submodule has uncommitted local changes; committing the parent pointer now would pin a state no one else can reproduce, since those changes exist only in the local working tree.
## Operations
- **Clone a repo that has submodules**: `rtk git clone --recurse-submodules <url>` (one step, Git 2.13+) or `rtk git clone <url>` followed by `rtk git submodule update --init --recursive`.
- **Add a submodule**: `rtk git submodule add <url> <path>` (`-b <branch>` to track a branch instead of a pinned commit, `--depth 1` for a shallow clone, `-f` to force past a gitignored path or name conflict, `--name <name>` when the logical name should differ from the path). Stages a `.gitmodules` entry and a gitlink — a commit is still required.
- **Initialize**: `rtk git submodule init [<path>...]` copies submodule URLs from `.gitmodules` to `.git/config`. This is the point at which local URL overrides can be edited before fetching. Does not clone — use `update` (or `update --init` to run both in one step).
- **Update (clone + checkout)**: `rtk git submodule update --init --recursive` is the common case — checks out the recorded commit in detached HEAD. Add `--remote --merge` (or `--remote --rebase`) to track the branch tip instead, `--jobs <n>` for parallel clones, `-f` to discard local changes. Full flag table: `references/submodules.md`.
- **Inspect status**: `rtk git submodule status --recursive` (add `--cached` to show SHAs in the superproject index instead of the working tree). Status prefixes: `-` not initialized, `+` diverged from the superproject's recorded commit, `U` merge conflict.
- **Sync and rebind URLs**: `rtk git submodule sync --recursive` after an upstream URL rename propagates `.gitmodules` changes into `.git/config`. `rtk git submodule set-url <path> <url>` changes a URL directly; `rtk git submodule set-branch -b <branch> <path>` sets the tracking branch used by `update --remote`.
- **Override a submodule URL locally (private mirror)**: local-only, doesn't propagate to collaborators, and gets overwritten by the next `sync`. Full steps: `references/submodules.md`.
- **Run a command across all submodules**: `rtk git submodule foreach --recursive '<command>'`. Shell variables available inside `<command>` (`$name`, `$sm_path`, `$displaypath`, `$sha1`, `$toplevel`): `references/submodules.md`.
- **Deinit (unregister without removing)**: `rtk git submodule deinit <path>` (`--all` for every submodule, `-f` if local modifications are present) clears the `.git/config` section and empties the working tree. **`deinit` is not removal** — the `.gitmodules` entry and the gitlink in the superproject's index are untouched.
- **Safe removal** (destructive; confirm before executing) — full three-step sequence including the manual `.git/modules/` cleanup: `references/submodules.md`.
- **Move an embedded `.git` into `.git/modules/`**: `rtk git submodule absorbgitdirs [<path>...]` — needed when a submodule was created or copied without going through `git submodule add`. Details: `references/submodules.md`.
## Configuration
`.gitmodules` (version-controlled, shared with collaborators):
| Key | Purpose |
|---|---|
| `submodule.<name>.path` | Working tree path |
| `submodule.<name>.url` | Remote URL |
| `submodule.<name>.branch` | Branch used by `update --remote` |
| `submodule.<name>.update` | Default update procedure |
| `submodule.<name>.shallow` | Recommend shallow clone |
`.git/config` (local only, populated by `init`):
| Key | Purpose |
|---|---|
| `submodule.<name>.url` | Local URL override |
| `submodule.<name>.update` | Local procedure override |
| `submodule.fetchJobs` | Default parallelism for `update --jobs` |
| `submodule.recurse` | Auto-recurse submodule updates on `pull`/`push`/etc. |
```bash
rtk git config submodule.recurse true # keep submodules pinned automatically after every pull
```
## Agent output format
Return results as structured data:
```
operation: <clone|add|init|update|sync|set-url|set-branch|status|summary|absorbgitdirs|remove>
status: <success|error|partial>
message: <human-readable summary>
details:
- <submodule-path>: <state>
conflicts: [<submodule-path>, ...] # if any
next_step: <recovery action if applicable>
```
For errors, include the git command output and recommend recovery (e.g., `git submodule deinit`, force-update, or URL override).

View File

@@ -0,0 +1,15 @@
---
metadata:
source_keys:
- git-scm-submodule-docs
---
# References
## submodules.md
Deep-dive reference: full `update` flag table, workflow patterns (clone, add, keep-pinned, update-to-latest, override URL), the complete safe-removal sequence, `absorbgitdirs`, and `foreach` shell variables. Load when SKILL.md's condensed Operations list isn't enough detail.
## sources.md
Research sources that informed this skill — provenance chain for git-scm-submodule-docs reference material.

View File

@@ -0,0 +1,29 @@
---
topic: submodules
source_keys:
- git-scm-submodule-docs
---
## git-scm-submodule-docs
**Description:** Official git-scm.com reference for `git submodule` — all subcommands, flags, configuration keys, and behaviour details.
**Source:** https://git-scm.com/docs/git-submodule
- **Research doc:** plugins/git/docs/research/docs/git/submodules.md (whole-document reference — the research doc is organized by descriptive prose headings such as "Concept Overview" and "Key Commands" rather than a heading matching this slug; this key covers the entire doc, not a single section)
**Contributing files:**
- SKILL.md (all sections)
- references/submodules.md (all sections)
---
Other source keys extracted during the git plugin research phase inform sibling skills in the git workflow suite, not this one:
- `context7-git-htmldocs` — git:branches, git:history, git:remotes
- `git-scm-docs` — git:configuration
- `git-scm-worktree-docs` — git:worktrees
- `nvie-gitflow-post`, `atlassian-gitflow-tutorial`, `gitflow-cheatsheet` — git:branches
- `conventional-commits-spec`, `commitlint-config-conventional` — git:commits
- `git-scm-push-docs`, `git-scm-fetch-docs`, `git-scm-pull-docs`, `git-scm-remote-docs` — git:remotes
- `git-scm-bisect-docs`, `git-scm-log-docs`, `git-scm-diff-docs` — git:history

View File

@@ -0,0 +1,93 @@
---
topic: submodules
source_keys:
- git-scm-submodule-docs
---
# Submodules — Deep Reference
## Update flag reference
| Flag | Meaning |
|---|---|
| `--init` | Run init first (avoids a separate step) |
| `--remote` | Use the submodule's remote branch tip instead of the superproject's recorded commit |
| `--checkout` | Detached HEAD at recorded commit (default) |
| `--rebase` | Rebase current branch onto recorded commit |
| `--merge` | Merge recorded commit into current branch |
| `--recursive` | Operate on nested submodules |
| `--jobs <n>` | Parallel clone (defaults to `submodule.fetchJobs`) |
| `-N` / `--no-fetch` | Skip remote fetch |
| `--depth <n>` | Shallow clone |
| `--filter <spec>` | Partial clone filter |
## Workflow patterns
### Clone a repo with submodules
```bash
git clone --recurse-submodules <url> # Git 2.13+, one step
# or
git clone <url>
git submodule update --init --recursive
```
### Add a dependency as a submodule
```bash
git submodule add https://github.com/org/lib.git libs/lib
git commit -m "chore: add lib as submodule"
```
### Keep submodules pinned to the superproject's recorded commit
```bash
git submodule update --recursive # after every git pull
git config submodule.recurse true # do this automatically on pull
```
### Update submodules to the latest commit on their tracked branch
```bash
git submodule update --remote --merge --recursive
git commit -am "chore: update submodules to latest"
```
### Override a submodule URL locally (private mirror)
```bash
git submodule init
# edit .git/config: submodule.<name>.url = <mirror-url>
git submodule update
```
Local-only override (`.git/config`, not `.gitmodules`) — doesn't propagate to collaborators. Re-running `sync` overwrites it with the `.gitmodules` URL.
## Removal, in full
`deinit` alone does not remove a submodule — it only clears `.git/config` and empties the working tree. To fully remove:
```bash
git submodule deinit -f <path> # unregister from .git/config
git rm <path> # remove .gitmodules entry + gitlink from index
rm -rf .git/modules/<name>/ # stale git dir; not tracked by git, not auto-cleaned
git commit -m "chore: remove <name> submodule"
```
`.git/modules/<name>/` persisting after `git rm` will block re-adding the same path until manually deleted.
## Relocate an embedded `.git` directory
```bash
git submodule absorbgitdirs [<path>...]
```
Moves a submodule's own `.git` directory into the superproject's `.git/modules/<name>/`, linking it back with a `.git` pointer file. Needed when a submodule was created or copied without going through `git submodule add` (e.g. converting a plain nested repo into a proper submodule).
## `foreach` shell variables
Available inside the `<command>` argument to `git submodule foreach`:
| Variable | Meaning |
|---|---|
| `$name` | Logical submodule name |
| `$sm_path` | Path relative to superproject root |
| `$displaypath` | Path relative to current working directory |
| `$sha1` | Recorded commit SHA |
| `$toplevel` | Superproject's root path |
```bash
git submodule foreach --recursive '<command>'
git submodule foreach 'git pull origin main || :' # || : continues past failures
```

View File

@@ -0,0 +1,24 @@
# git-workflow
Human-friendly interface for interactive git workflows with conversational prompts, progress guidance, and safety confirmations.
## What it does
This skill wraps the `git-orchestrate` agent to provide an interactive, educational interface for humans performing git workflows. It handles commits, branch management, history inspection, submodules, worktrees, and remotes. The skill parses user intent, gathers session context, invokes the orchestrator, and presents results in plain language with inline help, progress updates, and explanations of what's happening. It enforces confirmation gates for destructive operations (force-push, branch deletion, rebasing with history loss, force-checkout) and provides best-practices guidance throughout.
## Usage
```
/git-workflow
```
Describe your git workflow: commit, create a branch, rebase, inspect history, manage submodules, switch worktrees, or manage remotes. The skill will prompt for any missing details and guide you through the workflow.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `README.md` | This file |
| `references/README.md` | Describes the references directory contents |
| `references/sources.md` | Research sources and provenance |

View File

@@ -0,0 +1,65 @@
---
name: git-workflow
description: >
Use when a human user wants to perform git workflows interactively — commits, branch management,
history inspection, submodules, worktrees, or remotes. Provides a friendly, conversational
interface with clarification prompts ("Which branch base?"), progress updates, inline help,
best practices guidance, and confirmation dialogs for destructive operations. Guides users
through complex git patterns even if they don't mention every detail. Do not use when the
caller is an agent—agents should invoke git-orchestrate directly for deterministic, composable execution.
metadata:
category: git
source_keys:
- nvie-gitflow-post
- atlassian-gitflow-tutorial
- gitflow-cheatsheet
- context7-git-htmldocs
- org-git-conventions
---
## Gotchas
- This skill is specifically for **human interaction**. If the caller is an agent, invoke `git-orchestrate` directly instead—this skill adds UI overhead agents don't need.
- Session context from previous git operations (branch names, commit strategy) persists during a single multi-step user request, then clears. Users don't need to re-provide decisions within one workflow.
- Destructive operations require explicit confirmation: force-push, branch deletion, rebase with history loss, force-checkout. Users must confirm interactively; the skill never proceeds without their approval on destructive ops.
- Run git commands through `rtk git <command>` rather than bare `git <command>` for parent-repo operations — this is a mandated org wrapper, not an optional style choice. Drop into a submodule's own directory for submodule-specific commands (see `git-submodules`).
### Hard rules
These are non-negotiable regardless of what the user asks for — surface them proactively rather than waiting for the user to hit them (`org-git-conventions`; sub-skills invoked directly by humans, like this one, carry their own local copy of these rules for readers who won't chain through `git-orchestrate`, so state them plainly rather than assuming the user already knows them):
- Never skip hooks with `--no-verify` — hooks are the automated QA gate, and bypassing them breaks the pipeline for everyone downstream.
- Never force-push `main` or `master`.
- Keep commits atomic — each commit should represent one logical, independently reviewable and reversible change.
- Every commit must leave the repository in a working state (buildable/testable where practical).
- Commit messages explain **why**, not **what** — the diff already documents what changed.
- Never commit secrets, credentials, or environment-specific config.
- Use Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`, etc.).
- Reference related issues, ADRs, or design documents using Git trailers when applicable.
If a user's request conflicts with a hard rule (e.g. "force-push main to fix this"), explain the rule and propose a safe alternative instead of complying.
## Workflow
When a user wants to perform git workflows:
1. **Parse the user's intent** — extract the high-level task (commit, create branch, rebase, inspect history, etc.) and any explicit options they mentioned.
2. **Build session context** — gather repo state, current branch, any prior decisions in this workflow (branch intent for commit messages, base branch for rebasing, etc.).
3. **Invoke git-orchestrate agent** — call it with:
- `operation`: the git operation (e.g., "commit", "create-branch", "rebase")
- `parameters`: user-provided or inferred options
- `context`: decisions and repo state from prior steps in this workflow
- `confirm`: `true` if a destructive op and the user confirmed, otherwise omit
4. **Handle the response** — if orchestrator succeeds, present results in plain language with progress updates and explanations. If it fails, show the error reason and suggest recovery actions.
5. **Clarification prompts** — if the orchestrator needs more information (e.g., "Which branch should this be based on?"), prompt the user conversationally and loop back with the user's input.
6. **Confirmation gates** — before executing any destructive op (force-push, branch deletion, rebase, force-checkout), show what will happen and ask "Proceed?" If the user declines, cancel gracefully.
## Interaction style
- **Conversational**: Use natural language, not technical jargon. "Let me rebase your changes onto main" not "Running git rebase --interactive main".
- **Pedagogical**: Explain what each step does and why. "I'm squashing your last 3 commits into one clean commit" not just "Squashing commits".
- **Guided**: Offer inline help. When users mention ambiguous steps, suggest best practices. Match the tip to the repo's branching model: for Gitflow-style repos, "Tip: Feature branches branch off `develop`, not `main` — `main` only tracks released code." For trunk-based/GitHub Flow repos, "Tip: Short-lived feature branches off `main` keep merges small and reviewable."
- **Transparent**: Show progress. "Creating branch feature/user-auth..." then "✓ Branch created. Ready to commit." Humans benefit from seeing workflow state.
- **Safe**: Always confirm before destructive ops. Never silently rewrite history or force-push without explicit user approval.

View File

@@ -0,0 +1,16 @@
---
source_keys:
- nvie-gitflow-post
- atlassian-gitflow-tutorial
- gitflow-cheatsheet
- context7-git-htmldocs
- org-git-conventions
---
# References
This directory contains provenance metadata and research sources for the `git-workflow` skill.
## Files
- `sources.md` — Extracted research sources and their contributing documents

View File

@@ -0,0 +1,59 @@
---
# Research sources referenced by this skill
# Each entry documents where the skill's guidance came from.
---
## nvie-gitflow-post
**Description:** Original 2010 post by Vincent Driessen introducing the Gitflow branching model, including a 2020 reflection note recommending GitHub Flow for continuous delivery teams.
**Source:** https://nvie.com/posts/a-successful-git-branching-model/
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Interaction style — branching-model-aware tips)
## atlassian-gitflow-tutorial
**Description:** Atlassian's comprehensive Gitflow tutorial covering all five branch types, lifecycle steps, and CLI usage.
**Source:** https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Interaction style — branching-model-aware tips)
## gitflow-cheatsheet
**Description:** Visual cheatsheet for the git-flow CLI commands (git-flow-avh fork), covering all subcommands for feature, release, and hotfix branches.
**Source:** https://danielkummer.github.io/git-flow-cheatsheet/
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
**Contributing files:**
- SKILL.md (Interaction style — branching-model-aware tips)
## context7-git-htmldocs
**Description:** Official Git HTML documentation from the git/htmldocs repository — covers all commands, concepts, and internals.
**Source:** context7:/git/htmldocs
- **Research doc:** plugins/git/docs/research/docs/git/overview.md (whole-document reference)
**Contributing files:**
- SKILL.md (Workflow — general git operation vocabulary)
## org-git-conventions
**Description:** This org's internal git conventions (hard rules on hooks, force-push, atomic commits, secrets, Conventional Commits, trailers, and the `rtk git` wrapper requirement). Originally maintained as a standalone instruction file loaded into every agent's context; embedded directly into this skill because that central file has been removed from the repo, and skill content must stay self-contained after plugin installation.
**Source:** org-internal (formerly `core/instructions/git.md` in this repo, prior to its removal)
- **Research doc:** none — org convention, not part of the plugin's research corpus (no `plugins/git/docs/research/` topic file backs this entry)
**Contributing files:**
- SKILL.md (Gotchas — Hard rules subsection, rtk git note)

View File

@@ -0,0 +1,24 @@
# git-worktrees
Manage git worktrees to enable multi-branch parallel development across isolated directories.
## What it does
This skill handles worktree operations within the git workflow suite. It creates, lists, locks/unlocks, moves, removes, prunes, and repairs worktrees — letting an agent work on multiple branches simultaneously without stashing. It returns structured results (paths, branches, lock status) suitable for agent composition.
## Usage
```
/git-worktrees
```
Describe your worktree task: create a worktree for a branch, list existing worktrees, lock one for removable media, move, remove, prune, or repair. The skill will handle the operation with appropriate safety checks and return results.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/README.md` | Describes the references directory contents |
| `references/worktrees.md` | Full `add` flag table, sparse-checkout, removable-media locking, remote disambiguation, configuration |
| `references/sources.md` | Research sources and provenance |

View File

@@ -0,0 +1,125 @@
---
name: git-worktrees
description: >
Manage Git worktrees to enable multi-branch parallel development across isolated directories.
Use when the user needs to work on multiple branches simultaneously without stashing, switch between feature/hotfix/experimental work, or coordinate code reviews alongside ongoing development.
Handles creation, listing, locking, moving, removal, pruning, and repair of worktrees.
Provides structured results (paths, branches, lock status) for agent composition in git orchestration workflows.
Do not use when only inspecting a single branch or when the user needs standard checkout/stash workflows.
metadata:
category: git
source_keys:
- git-scm-worktree-docs
---
## Concept
A worktree lets you check out multiple branches simultaneously from one repository, each in its own directory. All worktrees share the same objects, config, and most refs (`refs/`). Each worktree has its own `HEAD`, index, and per-worktree metadata (`ORIG_HEAD`, `MERGE_HEAD`, `refs/bisect/`, `refs/worktree/`, `refs/rewritten/`) stored at `$GIT_DIR/worktrees/<name>/`. The **main worktree** (from `git init`/`git clone`) is exactly one per repo and cannot be removed; **linked worktrees** are the additional ones created via `git worktree add`.
## Gotchas
- **A branch can only be checked out in one worktree at a time.** Attempting `git worktree add` for an already-checked-out branch fails unless you pass `--force`. Use `--force` only when intentional.
- **Submodules are unsupported and block operations.** Repos with submodules have incomplete worktree support. Worktrees containing submodules cannot be moved and require `--force` to remove.
- **Never manually `rm -rf` a worktree directory.** This leaves stale metadata in `$GIT_DIR/worktrees/`. Always use `git worktree remove`. If already deleted, run `git worktree prune` to clean up.
- **Manual moves break bidirectional pointers.** If a worktree directory is moved outside of `git worktree move`, run `git worktree repair` to fix connections.
- **Force-flag escalation with locks.** Removing or moving a locked worktree requires `-ff` (two flags), not just `-f`.
- **Worktree identification is by full path, unique basename, or unique partial path.** Ambiguous names error. Use `git worktree list` to see available identifiers.
- **`--lock` on `add` is atomic; create-then-lock has a race window.** Use `--lock` directly on `git worktree add` when consistency matters.
- **`extensions.worktreeConfig = true` is a one-way door.** It enables per-worktree config (`git config --worktree ...`) but makes the repo refuse to open in older Git versions. Once set, `core.bare`/`core.worktree` must live in `config.worktree`, not `config`. Don't enable it unless per-worktree config is actually needed.
## Common Operations
**Create and switch to a new worktree** — default approach:
```bash
git worktree add -b <new-branch> <path>
cd <path>
```
This creates a new branch and checks it out in a new directory. Other branches cannot be checked out elsewhere simultaneously.
**Create-or-reset a branch**: `git worktree add -B <branch> <path>` — like `-b` but resets the branch to HEAD if it already exists.
**Create a worktree for an existing remote branch**:
```bash
git worktree add <path> <remote>/<branch>
```
For ambiguous names across remotes, disambiguate via `checkout.defaultRemote` config or `--guess-remote`. Full flag table and detail: `references/worktrees.md`.
**Throwaway experiment in detached HEAD**:
```bash
git worktree add -d ../experiment # or --detach
# experiment freely, no branch created
git worktree remove ../experiment
```
**List all worktrees with state**:
```bash
git worktree list -v # human-readable with lock/prune reasons
git worktree list --porcelain -z # machine-readable, NUL-terminated
```
**Move a worktree to a new path**:
```bash
git worktree move <current-path> <new-path>
# Cannot move: main worktree, worktrees with submodules
# To override safeguards: -f; to override locked state too: -ff
```
**Remove a worktree**:
```bash
git worktree remove <path> # only if clean
git worktree remove -f <path> # force-remove unclean
git worktree remove -ff <path> # force-remove even if locked
```
**Prune stale metadata**:
```bash
git worktree prune --dry-run # preview what would be removed
git worktree prune # clean up orphaned metadata
```
Also triggered by `git gc`, controlled by `gc.worktreePruneExpire` config.
**Repair broken connections** (after a manual move):
```bash
git worktree repair # from main worktree or after it was moved
git worktree repair <path> # reconnect a specific linked worktree
```
Sparse-checkout worktrees, locking for removable media, the full `add` flag table, and the config key reference: `references/worktrees.md`.
## Worked Examples
**Emergency fix without disrupting current work** — no stashing needed, ongoing work in the main worktree is untouched:
```bash
git worktree add -b emergency-fix ../temp main
cd ../temp
# fix, commit
git commit -a -m "fix: critical production bug"
cd -
git worktree remove ../temp
```
**Review a PR branch alongside your current work** — no context switch, both branches stay checked out:
```bash
git worktree add ../review-pr-123 origin/feature-xyz
# open ../review-pr-123 in a second editor window or terminal
```
## Return Format for Agents
When invoking worktree operations, return structured results:
```yaml
worktrees:
- path: <directory-path>
branch: <branch-name>
commit: <short-hash>
locked: <true/false>
lock_reason: <reason or empty>
- ...
```
Derive these fields from `git worktree list --porcelain -z` — its `worktree`/`branch`/`HEAD`/`locked` lines map directly to `path`/`branch`/`commit`/`locked`+`lock_reason`.
For single operations, include the operation result (e.g., `created: true`, `removed: true`, `moved: true`).
For multi-step flows spanning branch strategy plus worktree setup, compose with the `git-workflow` skill — it handles the broader orchestration, this skill handles the worktree mechanics.

View File

@@ -0,0 +1,13 @@
---
source_keys:
- git-scm-worktree-docs
---
# References
This directory contains provenance metadata and research sources for the `git-worktrees` skill.
## Files
- `sources.md` — Extracted research sources and their contributing documents
- `worktrees.md` — Full `add` flag table, sparse-checkout setup, removable-media locking, remote-branch disambiguation, and the config key reference

View File

@@ -0,0 +1,16 @@
---
# Research sources referenced by this skill
# Each entry documents where the skill's guidance came from.
---
## git-scm-worktree-docs
**Description:** Git SCM official documentation for `git worktree` command — creating, listing, locking, moving, removing, pruning, and repairing linked worktrees; shared vs. per-worktree state; worktree-scoped config.
**Source:** https://git-scm.com/docs/git-worktree
- **Research doc:** plugins/git/docs/research/docs/git/worktrees.md (whole-document reference — covers `## Concept Overview`, `## Key Commands`, `## Workflow Patterns`, `## Common Gotchas`, `## Configuration`)
**Contributing files:**
- SKILL.md (Concept, Gotchas, Common Operations, Worked Examples, Return Format)
- references/worktrees.md (full `add` flag table, sparse-checkout, removable media, remote disambiguation, configuration)

View File

@@ -0,0 +1,63 @@
---
topic: worktrees
source_keys:
- git-scm-worktree-docs
---
## Full `add` flag table
| Flag | Meaning |
|---|---|
| `-b <branch>` | Create and check out a new branch; fails if it exists |
| `-B <branch>` | Like `-b` but resets the branch if it already exists |
| `-d` / `--detach` | Detach HEAD; useful for throwaway experiments |
| `--orphan` | Create empty unborn branch |
| `--no-checkout` | Suppress initial checkout (for sparse-checkout setup) |
| `--guess-remote` | Look for a matching remote-tracking branch by path basename |
| `--lock [--reason <str>]` | Lock immediately on creation (atomic; avoids race vs. add-then-lock) |
| `-f` / `--force` | Allow when branch is already checked out elsewhere |
| `--relative-paths` | Link via relative paths (portable across moves) |
Using `-` as `<commit-ish>` is shorthand for `@{-1}` (the branch checked out before the current one), e.g. `git worktree add <path> -`.
## New unborn branch
```bash
git worktree add --orphan -b <branch> <path>
```
Creates an empty branch with no commits.
## Sparse-checkout worktree
Suppress the initial checkout to configure sparse-checkout first:
```bash
git worktree add --no-checkout ../sparse main
cd ../sparse
git sparse-checkout init --cone
git sparse-checkout set src/
git checkout main
```
## Worktree on removable media
```bash
git worktree add --lock --reason "external SSD" <path> <branch>
git worktree unlock <path> # when reconnected
```
## Remote-branch disambiguation
```bash
git worktree add <path> <remote>/<branch>
```
For ambiguous names across remotes, `checkout.defaultRemote` config disambiguates explicitly, or `--guess-remote` auto-matches by path basename (default controlled by `worktree.guessRemote` config). If a branch name matches multiple remotes during `worktree add` and neither is set, Git refuses rather than guessing.
## Configuration
| Key | Effect |
|---|---|
| `worktree.guessRemote` | Default for `--guess-remote` on `git worktree add` |
| `worktree.useRelativePaths` | Default for `--relative-paths` on `git worktree add` (link via relative paths — portable across moves) |
| `gc.worktreePruneExpire` | How long before stale worktree metadata is pruned by `git gc` |
| `extensions.worktreeConfig` | Enable per-worktree config scope (`config.worktree` file) — see Gotchas in SKILL.md |
| `checkout.defaultRemote` | Disambiguates which remote to use when a branch name matches multiple remotes during `worktree add` |

View File

@@ -0,0 +1,24 @@
# pc-author
Create, add, remove, update, and configure `.pre-commit-config.yaml`.
## What it does
Manages the pre-commit configuration file in any git repo. When invoked, it scans the repo for languages, proposes appropriate hooks with rationale, and writes or modifies `.pre-commit-config.yaml`. It validates every write with `pre-commit validate-config` and flags stale revision pins. It does not run hooks or install them into `.git/hooks/` — use `pc-run` for that.
## Usage
```
/pc-author
```
Invoke with no arguments. The skill determines from context whether to create a new config or modify an existing one.
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/hooks-by-language.md` | Hook recommendations by detected language/extension |
| `references/README.md` | Index of files in references/ |
| `references/sources.md` | Provenance — research sources that informed this skill |

View File

@@ -0,0 +1,91 @@
---
name: pc-author
description: >
Use when the user wants to create, add hooks to, remove hooks from, update,
or configure .pre-commit-config.yaml. Triggers on: "set up pre-commit",
"add a hook", "remove this hook", "configure pre-commit", "create a pre-commit
config", "disable trailing whitespace hook", "add shellcheck", "update my
pre-commit config", even if the user does not name pre-commit explicitly.
Do not use for running hooks, installing git hooks, or bumping revision pins
— use pc-run for those.
allowed-tools: Bash Read Write Edit
metadata:
category: devtools
source_keys:
- context7-pre-commit-com
- pre-commit-com
- context7-pre-commit-hooks
- pre-commit-hooks-github
---
## Gotchas
- `rev` must be an immutable tag or commit SHA — never a branch name. `pre-commit autoupdate` breaks silently on branches.
- Fixers (`trailing-whitespace`, `end-of-file-fixer`, `pretty-format-json`) modify files but do NOT auto-stage them. The commit is blocked; the user must re-stage and recommit. Warn when adding fixers.
- `pre-commit validate-config` catches YAML structure errors but does NOT check whether hook `id`s exist in the target repo's manifest, and does NOT download or run hooks. It is fast; run it after every write.
- When removing a hook leaves its repo block with zero hooks, delete the entire repo block — an empty `hooks: []` causes `validate-config` to fail.
- `language: system` and `language: script` are deprecated names. Use `language: unsupported` and `language: unsupported_script` for new local hooks.
## Route
Check before acting:
- `.pre-commit-config.yaml` does not exist → **Create from scratch**
- File exists → **Modify existing**
## Create from scratch
1. Run a shallow extension scan:
```bash
git ls-files | grep -oE '\.[a-z]+$' | sort | uniq -c | sort -rn
```
2. Read `references/hooks-by-language.md` to map detected extensions to recommended hooks. For a minimal starting point instead of a full recommendation set, `pre-commit sample-config > .pre-commit-config.yaml` prints a small starter config to build on.
3. State the proposed config in full before writing. Wait for user confirmation.
4. Write `.pre-commit-config.yaml`.
5. Run `pre-commit validate-config`. If non-zero: show the error, fix it, re-validate. Never leave a broken config.
## Modify existing
Read `.pre-commit-config.yaml` first. Note any stale `rev` values (see **Rev staleness** below) but do not change them.
### Adding a hook
1. Run a shallow extension scan to detect languages in the repo:
```bash
git ls-files | grep -oE '\.[a-z]+$' | sort | uniq -c | sort -rn
```
2. Read `references/hooks-by-language.md` for the correct repo URL, rev, and recommended args for any hook before writing.
3. Check for duplicates — if the same hook ID or equivalent tool already exists in the config, say so and stop.
4. To sanity-check a hook against the repo's actual files before committing to it in config, smoke-test it with `pre-commit try-repo <repo-url> <hook-id> --verbose` (or a local path for hooks under development). This runs the hook without writing anything.
5. If the hook's source repo already exists in the config, add the hook under that repo block. Otherwise append a new repo block.
6. State the proposed addition. Wait for confirmation.
7. Write. Run `pre-commit validate-config`. If non-zero: show error, fix, re-validate.
### Removing a hook
1. Identify the hook entry and its repo block.
2. State what will be removed: hook ID, and whether the parent repo block will also be deleted (if it would have zero hooks remaining). Wait for confirmation.
3. Remove the hook entry. If the repo block now has zero hooks remaining, remove the entire repo block.
4. Write. Run `pre-commit validate-config`. If non-zero: revert the edit, show the error, and stop — do not leave a broken config (removal edits are not safely auto-fixable, unlike a bad new hook block, which can usually be corrected in place).
### Configuring top-level keys
Only when the user explicitly asks. Valid keys: `fail_fast`, `default_stages`, `default_language_version`, `minimum_pre_commit_version`, `exclude`, `files`, `default_install_hook_types`.
State the proposed change and wait for confirmation before writing.
## Rev staleness
When reading the config, for each repo listed in `references/hooks-by-language.md`, compare its `rev` in the user's config against the rev in that file. Flag any mismatch as potentially outdated and tell the user to run `pc-run` to autoupdate. Repos not in the reference cannot be checked — skip them silently. Do not modify `rev` values yourself.
The reference table's pins can themselves go stale between updates — treat a mismatch as a prompt to check, not a certainty. `pre-commit autoupdate` (via `pc-run`) is the authoritative source for what the current rev actually is.
## Scope boundary
This skill manages `.pre-commit-config.yaml` only. It does not:
- Author `.pre-commit-hooks.yaml` (publishing hooks for external consumers)
- Run `pre-commit install`
- Execute hooks or run the test suite
- Bump `rev` values
For those operations, use `pc-run`.

View File

@@ -0,0 +1,14 @@
---
source_keys:
- context7-pre-commit-com
- pre-commit-com
- context7-pre-commit-hooks
- pre-commit-hooks-github
---
# references/
| File | Purpose |
|---|---|
| `hooks-by-language.md` | Hook recommendations by language/context — repo, rev, and rationale for adding hooks |
| `sources.md` | Provenance: research sources that informed this skill |

View File

@@ -0,0 +1,120 @@
---
source_keys:
- context7-pre-commit-com
- pre-commit-com
- context7-pre-commit-hooks
- pre-commit-hooks-github
---
# Hook Recommendations by Language / Context
Use this table when creating a config from scratch or recommending hooks to add.
Always check the existing config for duplicates before proposing.
## Universal (recommend for every repo)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `end-of-file-fixer` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Ensures files end with a newline — prevents spurious diffs |
| `trailing-whitespace` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Strips trailing whitespace — prevents invisible diff noise |
| `check-merge-conflict` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Catches unresolved merge markers before commit |
| `detect-private-key` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Blocks PEM private key material |
| `check-added-large-files` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Blocks accidentally committing large binary files |
| `check-case-conflict` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Catches filenames that would collide on case-insensitive filesystems |
| `mixed-line-ending` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Normalizes line endings |
| `no-commit-to-branch` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Blocks direct commits to protected branches — defaults to blocking `main`+`master` with no args; add `args: [--branch, <name>]` only to protect additional branch names |
## Shell (`.sh`)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `shellcheck` | `https://github.com/jumanjihouse/pre-commit-hooks` | `3.0.0` | **Unverified — not in research corpus, verify upstream before use.** Static analysis for shell scripts; catches common errors |
Recommended args: `args: [--severity=warning]`
## Python (`.py`)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `check-ast` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Validates Python files parse as valid AST |
| `check-builtin-literals` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Enforces literal syntax for `dict()`, `list()` |
For formatting: check if `black`, `ruff`, or `isort` is already configured in `pyproject.toml` before recommending them.
## JSON (`.json`)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `check-json` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Validates JSON parses correctly |
| `pretty-format-json` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Auto-formats JSON (fixer — warns user to re-stage after commit) |
## YAML (`.yaml`, `.yml`)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `check-yaml` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Validates YAML parses correctly |
For Kubernetes/Helm YAML with custom tags, add `args: ['--unsafe']` and `exclude: ^helm/templates/`.
## TOML (`.toml`)
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `check-toml` | `https://github.com/pre-commit/pre-commit-hooks` | `v6.0.0` | Validates TOML parses correctly |
## Secrets / security
| Hook ID | Repo | Rev | Rationale |
|---------|------|-----|-----------|
| `gitleaks` | `https://github.com/gitleaks/gitleaks` | `v8.30.1` | **Unverified — not in research corpus, verify upstream before use.** Scans for secrets and high-entropy strings |
## Commit message
| Hook ID | Repo | Rev | Stage | Rationale |
|---------|------|-----|-------|-----------|
| `conventional-pre-commit` | `https://github.com/compilerla/conventional-pre-commit` | `v2.4.0` | `commit-msg` | Enforces Conventional Commits format |
When adding commit-msg hooks, also add `default_install_hook_types: [pre-commit, commit-msg]` to the top-level config if not already present.
## Meta-validation (add last, after all other repos)
```yaml
- repo: meta
hooks:
- id: check-hooks-apply # catches hooks that match no files
- id: check-useless-excludes # catches exclude patterns that match no files
```
## Local hooks (repo: local)
Use for repo-specific scripts that don't belong in an external hook repo.
```yaml
- repo: local
hooks:
- id: run-tests
name: Run test suite
entry: bash tests/run-tests.sh
language: unsupported_script
pass_filenames: false
always_run: true
stages: [pre-push]
```
Language choices for local hooks:
- `unsupported` — system PATH tool (pre-commit does not manage env)
- `unsupported_script` — script at a repo-relative path
- `fail` — always-fail guard; `entry` text becomes the error message
- `python` — isolated venv; use `additional_dependencies` for pip packages
- `node` — isolated node env; `additional_dependencies` are npm packages
- `ruby` — isolated gem env; `additional_dependencies` are gems
- `golang` — builds from source; `additional_dependencies` are Go module paths
- `rust` — Cargo build
- `docker` — Docker image built from `entry`; use when no other language fits
- `docker_image` — pulls a pre-built Docker image by `entry`
- `conda` — Conda environment; conda-native hooks
- `coursier` — Coursier (Scala/JVM) environment; JVM hooks
## Rev pin freshness
The revs above were last verified current at time of writing (matched against the plugin's own research corpus in `docs/research/docs/pre-commit/`; rows marked "Unverified" have no such backing and must be checked against upstream before use). Since `pc-author`'s "Rev staleness" check treats this table as ground truth, a pin that goes stale here produces false-positive staleness warnings for users who already have a newer, correct rev. Re-verify these pins periodically (e.g. against each repo's latest release tag). When in doubt, treat `pre-commit autoupdate`'s own output as the authoritative staleness signal, not a mismatch against this table.

View File

@@ -0,0 +1,33 @@
# Sources
## context7-pre-commit-com
- **URL:** context7:/pre-commit/pre-commit.com
- **Description:** Official pre-commit.com documentation — installation, configuration schema, CLI reference, hook authoring, advanced features, troubleshooting
- **Contributing files:** SKILL.md, references/hooks-by-language.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/{overview,configuration,cli-reference,hook-authoring}.md
- **Status:** `extracted`
## pre-commit-com
- **URL:** https://pre-commit.com/
- **Description:** Pre-commit framework homepage — full docs covering install, config, CLI, hook authoring, stages, local hooks, meta hooks, hazmat helpers, CI integration
- **Contributing files:** SKILL.md, references/hooks-by-language.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/{overview,configuration,cli-reference,hook-authoring}.md
- **Status:** `extracted`
## context7-pre-commit-hooks
- **URL:** context7:/pre-commit/pre-commit-hooks
- **Description:** Official pre-commit-hooks collection — all available hook IDs with options and examples
- **Contributing files:** references/hooks-by-language.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/hooks-reference.md § pre-commit-hooks (official collection)
- **Status:** `extracted`
## pre-commit-hooks-github
- **URL:** https://raw.githubusercontent.com/pre-commit/pre-commit-hooks/main/README.md
- **Description:** Official pre-commit-hooks README — complete hook listing with all args, categories, deprecated hooks, and latest version (v6.0.0)
- **Contributing files:** references/hooks-by-language.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/hooks-reference.md § pre-commit-hooks (official collection), § Deprecated hooks
- **Status:** `extracted`

View File

@@ -0,0 +1,29 @@
# pc-run
Runs, installs, updates, and maintains pre-commit hooks in a local git clone.
## What it does
`pc-run` handles everything that happens *after* `.pre-commit-config.yaml` exists: wiring hooks into git, running them, bumping their versions, and maintaining the cache. When hooks fail, it identifies the cause and suggests a concrete fix — it does not auto-fix files or edit the config. For creating or editing `.pre-commit-config.yaml`, use `pc-author` instead.
## Before you start
- `pre-commit` must be installed and available on `PATH`
- A `.pre-commit-config.yaml` must exist at the repo root (use `pc-author` to create one)
## Usage
Common invocations:
- `/pc-run` — run all hooks against all files (default)
- `/pc-run install` — wire hooks into `.git/hooks/`
- `/pc-run autoupdate` — bump all `rev` values to latest
- `/pc-run clean` — wipe the pre-commit cache (requires confirmation)
## Files
| File | Purpose |
|------|---------|
| `SKILL.md` | Skill instructions for agents |
| `references/failure-patterns.md` | Hook failure causes and concrete fix suggestions |
| `references/sources.md` | Provenance: research sources that informed this skill |
| `references/README.md` | Directory index for references/ |

View File

@@ -0,0 +1,123 @@
---
name: pc-run
description: >
Use when the user wants to run pre-commit hooks, install git hooks, update
hook versions, or maintain the pre-commit cache. Triggers on: "run
pre-commit", "run all hooks", "check everything passes", "install hooks",
"wire hooks into git", "update hook versions", "autoupdate", "bump revs",
"clean the cache", "rebuild environments", "gc", "why is my hook failing",
"hooks aren't running". Do not use for creating or editing
`.pre-commit-config.yaml` — use `pc-author` for that.
compatibility: Requires pre-commit installed and available on PATH.
metadata:
category: devtools
source_keys:
- context7-pre-commit-com
- pre-commit-com
allowed-tools: Bash Read
---
## Gotchas
- Hooks not running on `git commit` almost always means `pre-commit install` was never run in this clone. Git hooks are per-clone — they are not committed to the repo.
- When a hook modifies files (e.g. `trailing-whitespace`, `end-of-file-fixer`), the commit is blocked intentionally — the staged version is stale. The fix is `git add -u && git commit`. Do NOT call `pre-commit install -f` here; that is for overwriting existing hooks, not re-staging.
- `pre-commit autoupdate` modifies `.pre-commit-config.yaml` in-place. Re-read the file after calling it to show the user the updated `rev` values.
- The `SKIP` env var requires exact hook `id` values, comma-separated, no spaces: `SKIP=check-yaml,gitleaks git commit -m "msg"`. A space after the comma silently skips nothing.
- Never use `git commit --no-verify` (or `-n`) to bypass a failing hook. Hooks are the automated QA gate; bypassing them breaks the pipeline. Diagnose and fix the failure instead — see the hook-specific guidance below and in `references/failure-patterns.md`.
- A stages mismatch — hook stage not installed — means the hook was added to the config but `pre-commit install` was not re-run with the correct `-t` flags. Hooks in stages not listed under `default_install_hook_types` will never fire.
## Route
Determine intent from the user's request, then execute the matching operation:
| User intent | Operation |
|---|---|
| "run", "check", "verify", "test hooks" | `pre-commit run --all-files` (default) |
| "staged", "simulate commit" | `pre-commit run` (staged files only) |
| "CI", "changed files only", "diff range" | `pre-commit run --from-ref <base> --to-ref <head>` — prefer this over `--all-files` on large repos |
| "install", "set up hooks", "wire into git" | `pre-commit install` — see Install |
| "pre-create environments", "install-hooks", "warm cache" | `pre-commit install-hooks` — see Install |
| "remove hooks", "uninstall", "tear down pre-commit" | `pre-commit uninstall` |
| "autoupdate", "update versions", "bump revs" | `pre-commit autoupdate` |
| "gc", "garbage collect" | `pre-commit gc` |
| "clean", "wipe cache", "rebuild from scratch" | `pre-commit clean` — see Clean |
If the intent is ambiguous, default to `pre-commit run --all-files`.
## Run
Default: `pre-commit run --all-files`. Never silently run staged-only.
```bash
pre-commit run --all-files
```
**When hooks fail**, read the output and:
1. Identify which hook failed and the specific cause. Be concrete: "gitleaks blocked `config.json` (high-entropy string on line 12)", not just "gitleaks failed".
2. Suggest a concrete next step. Common patterns are in `references/failure-patterns.md`.
3. Do NOT auto-fix code files. Do NOT modify `.pre-commit-config.yaml`. Those are the user's or `pc-author`'s responsibility.
If the user asks to run only staged files: `pre-commit run` (no `--all-files`).
If the user names a specific hook: `pre-commit run <hook-id>`.
## Install
Only run when the user explicitly asks to install or set up hooks.
Before running, check for existing hook files:
```bash
ls .git/hooks/
```
If any hook files exist (e.g. a hand-written `pre-commit`), `pre-commit install` does NOT refuse or error — it defaults to migration mode, which runs the existing hook and pre-commit's hooks both. Only `-f` replaces the existing hook file outright, and that replacement is not reversible via `pre-commit uninstall` — uninstall only removes pre-commit from `.git/hooks/`, it does not restore whatever hand-written hook `-f` overwrote. If files are present, tell the user: "Existing hook files found at `.git/hooks/<names>`. Plain `pre-commit install` will run both; `pre-commit install -f` will overwrite them permanently instead. Proceed with plain install, or overwrite?" Wait for confirmation before using `-f`.
```bash
pre-commit install
```
Re-run with `-t` flags when `default_install_hook_types` was changed or when hooks in non-default stages aren't firing:
```bash
pre-commit install -t pre-commit -t pre-push -t commit-msg
```
To pre-create all hook environments without running hooks (useful for CI warm-up or first-time setup):
```bash
pre-commit install-hooks
```
To remove pre-commit from `.git/hooks/` entirely:
```bash
pre-commit uninstall
```
## Autoupdate
```bash
pre-commit autoupdate
```
After it completes, read `.pre-commit-config.yaml` and report which `rev` values changed. If the user wants to pin to exact SHAs (for reproducibility): `pre-commit autoupdate --freeze`.
## Clean and GC
**`gc`** — removes only unused cached environments. Safe to run at any time:
```bash
pre-commit gc
```
**`clean`** — wipes the entire cache at `~/.cache/pre-commit`. All hook environments will be re-downloaded on next run. Require explicit confirmation before running:
> "This will wipe the entire pre-commit cache. All hook environments will be re-downloaded on next run. Proceed?"
Wait for the user to say yes before executing:
```bash
pre-commit clean
```

View File

@@ -0,0 +1,14 @@
---
source_keys:
- context7-pre-commit-com
- pre-commit-com
- context7-pre-commit-hooks
- pre-commit-hooks-github
---
# references/
| File | Purpose |
|---|---|
| `failure-patterns.md` | Hook failure causes and concrete fix suggestions — loaded when hooks fail |
| `sources.md` | Provenance: research sources that informed this skill |

View File

@@ -0,0 +1,130 @@
---
source_keys:
- context7-pre-commit-com
- pre-commit-com
---
# Hook Failure Patterns
Common hook failure causes and concrete next-step suggestions.
## Hook modified files — commit blocked
Cause: A fixer hook (e.g. `trailing-whitespace`, `end-of-file-fixer`, `pretty-format-json`) modified staged files. The commit is blocked because the staged version is now stale.
Fix: Re-stage and recommit.
```bash
git add -u
git commit -m "same message"
```
## Secret detected (gitleaks)
> Not sourced from the pre-commit research corpus (`context7-pre-commit-com`/`pre-commit-com` cover pre-commit itself, not gitleaks) — general tool knowledge, verify against gitleaks' own docs if precision matters.
Cause: gitleaks found a high-entropy string or known secret pattern in a staged file.
Suggestions:
- If it's a false positive: add a `# gitleaks:allow` inline comment, or add the path to `.gitleaksignore`.
- If it's a real secret: remove it from the file, rotate the credential, then commit.
## Shellcheck warning
> Not sourced from the pre-commit research corpus — general tool knowledge, verify against shellcheck's own docs if precision matters.
Cause: shellcheck found a shell script issue. The output includes the file path, line number, and SC-code.
Fix: Look up the SC-code on shellcheck.net or pass `--explain SCxxxx` to shellcheck for a detailed explanation. The most common fixes:
- SC2086 (unquoted variable): wrap in double quotes.
- SC2046 (unquoted command substitution): wrap in double quotes.
- SC2181 (check exit code of `$?`): use `if command; then` directly.
## `check-hooks-apply` fails
Cause: A hook's `files`/`types` filter matches zero files in the repo — the hook is dead weight.
Fix: Broaden the filter, or remove the hook if it no longer applies to this repo.
## `check-useless-excludes` fails
Cause: An `exclude` pattern matches no files.
Fix: Remove or fix the pattern.
## SSH cloning fails in CI
Cause: The CI environment lacks SSH credentials to clone hook repos over SSH.
Fix: Export `SSH_AUTH_SOCK` in the CI environment, or switch hook repo URLs to HTTPS.
## HTTP proxy needed
Cause: The CI/sandbox network requires a proxy to reach hook repos.
Fix:
```bash
export http_proxy=http://proxy.example.com:3128
export https_proxy=http://proxy.example.com:3128
export no_proxy=localhost,127.0.0.1
```
## `rev` is a branch name — `autoupdate` broke it
Cause: Branch refs are mutable and drift over time; pre-commit resolves them once at install time, so pinning to a branch name (instead of a tag or commit SHA) leads to silent version drift.
Fix:
```bash
pre-commit autoupdate # finds the latest tag and rewrites rev in place
```
## pretty-format-json fails but doesn't fix
Cause: `pretty-format-json` requires `args: [--autofix]` to modify files. Without it, the hook only fails.
Fix: The user (or `pc-author`) must add `args: [--autofix]` to the hook override in `.pre-commit-config.yaml`.
## Environment stale or broken
Cause: A hook's cached environment is corrupted or out of date.
Fix:
```bash
pre-commit clean # wipe all environments
pre-commit install-hooks # rebuild everything
```
Or less destructively:
```bash
pre-commit gc # remove only unused environments
```
## Hooks don't run on `git commit`
Cause: `pre-commit install` was never run in this clone.
Fix: `pre-commit install`. Git hooks are per-clone — they are not committed to the repo.
## Hook runs but matches wrong files (or no files)
Cause: The `files:` pattern uses `re.search()` not full-string match. A pattern that looks correct may match unexpectedly.
Diagnosis: `identify-cli <filename>` shows the type tags for a file. Verify `types:` filters against these.
## stages mismatch — hook never fires
Cause: Hook is defined for a stage (e.g. `pre-push`) but `pre-commit install` was not run with `-t pre-push`.
Fix:
```bash
pre-commit install -t pre-commit -t pre-push -t commit-msg
```
Or add `default_install_hook_types` to `.pre-commit-config.yaml` and re-run `pre-commit install`.
## `validate-config` schema error
Common causes:
- Missing `id` under a hook block
- Missing `rev` under a non-local repo block
- `repo: local` hook missing `language` or `entry`
- Indentation error (valid YAML but invalid pre-commit schema)

View File

@@ -0,0 +1,33 @@
# Sources
## context7-pre-commit-com
- **URL:** context7:/pre-commit/pre-commit.com
- **Description:** Official pre-commit.com documentation — installation, configuration schema, CLI reference, hook authoring, advanced features, troubleshooting
- **Contributing files:** SKILL.md, references/failure-patterns.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/{overview,cli-reference,troubleshooting}.md
- **Status:** `extracted`
## pre-commit-com
- **URL:** https://pre-commit.com/
- **Description:** Pre-commit framework homepage — full docs covering install, config, CLI, hook authoring, stages, local hooks, meta hooks, hazmat helpers, CI integration
- **Contributing files:** SKILL.md, references/failure-patterns.md
- **Research doc:** plugins/git/docs/research/docs/pre-commit/{overview,cli-reference,troubleshooting}.md
- **Status:** `extracted`
## context7-pre-commit-hooks
- **URL:** context7:/pre-commit/pre-commit-hooks
- **Description:** Official pre-commit-hooks collection — all available hook IDs with options and examples
- **Contributing files:** (none)
- **Research doc:** plugins/git/docs/research/docs/pre-commit/hooks-reference.md § "pre-commit-hooks (official collection)"
- **Status:** `extracted`
## pre-commit-hooks-github
- **URL:** https://raw.githubusercontent.com/pre-commit/pre-commit-hooks/main/README.md
- **Description:** Official pre-commit-hooks README — complete hook listing with all args, categories, deprecated hooks, and latest version
- **Contributing files:** (none)
- **Research doc:** plugins/git/docs/research/docs/pre-commit/hooks-reference.md § "pre-commit-hooks (official collection)"
- **Status:** `extracted`