Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
be6f666
feat: add source-control plugin (commit, pull-request, worktree skills)
kyle-sexton Jul 11, 2026
ebd451e
fix: exec bits, sourced-lib header, static-analyzable worktree preamble
kyle-sexton Jul 11, 2026
3de2d47
Merge remote-tracking branch 'origin/main' into HEAD
kyle-sexton Jul 11, 2026
75c4e4a
Merge remote-tracking branch 'origin/main' into feat/publish-source-c…
kyle-sexton Jul 11, 2026
4fcdfb7
fix: address Codex review findings (WIP-safe babysit checkout, all-su…
kyle-sexton Jul 11, 2026
c47b4de
fix: address Codex round-2 findings (terminal rebase states, inline-r…
kyle-sexton Jul 11, 2026
3c97c81
fix: match real gh pr checks bucket values in Monitor watch filter
kyle-sexton Jul 11, 2026
6f0ed75
ci: retrigger checks for head 3c97c81
kyle-sexton Jul 11, 2026
8371be0
Merge remote-tracking branch 'origin/main' into feat/publish-source-c…
kyle-sexton Jul 11, 2026
e0fa75f
fix: address round-4 review findings (own-branch babysit no-op, fork-…
kyle-sexton Jul 11, 2026
1b09b58
fix: fork-safe monitor checkout and rebase push targets
kyle-sexton Jul 11, 2026
3fff239
Merge remote-tracking branch 'origin/main' into feat/publish-source-c…
kyle-sexton Jul 11, 2026
ab42900
fix: round-6 review findings (repo-agnostic default branch in merge p…
kyle-sexton Jul 11, 2026
d544baf
fix: round-7 review findings (review-body reaction exemption, default…
kyle-sexton Jul 11, 2026
bb26d82
Merge remote-tracking branch 'origin/main' into feat/publish-source-c…
kyle-sexton Jul 11, 2026
cf90cfb
fix: round-8 review findings (plain [P-num] severity counting with re…
kyle-sexton Jul 11, 2026
8aa7ac9
fix: guard dirty worktrees before force removal (round-9 P1)
kyle-sexton Jul 11, 2026
b7fd0c7
Merge remote-tracking branch 'origin/main' into feat/publish-source-c…
kyle-sexton Jul 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@
"source": "./plugins/songwriting",
"category": "music",
"tags": ["songwriting", "lyrics", "pat-pattison", "suno", "music", "domain", "skill"]
},
{
"name": "source-control",
"source": "./plugins/source-control",
"category": "development",
"tags": ["delivery", "git", "github", "commit", "pull-request", "worktree", "ci", "skill"]
}
]
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Browse and manage with `/plugin`. To refresh after updates: `/plugin marketplace
| [`tdd`](plugins/tdd) | Skill | Ships a TDD knowledge base distilled from Beck's *TDD: By Example* and Khorikov's *Unit Testing: Principles, Practices, and Patterns* — fourteen author-attributed reference files behind a routing table plus a no-load quick decision guide, answering the WHY behind test design decisions. |
| [`claude-ops`](plugins/claude-ops) | Skills | Claude Code operations toolkit of three skills: `/claude-ops:claude-observability` (read locally captured telemetry — OTEL store, collector, hook-event JSONL, ccusage — with trend reports and store pruning), `/claude-ops:claude-troubleshooting` (search known Claude product bugs, check service health, maintain a persistent tracked-issue registry), and `/claude-ops:claude-code-changelog` (ingest Claude Code changelog entries and integrate them into the current repo). |
| [`songwriting`](plugins/songwriting) | Skills | Songwriting craft companion. Ships two skills: `/songwriting:pat-pattison` (Pat Pattison lyric-craft coaching — rhyme, meter, prosody, song form, object writing, metaphor, co-writing, daily practice, with a live Datamuse rhyme/vocabulary helper) and `/songwriting:suno` (Suno v5.5 prompt engineering — style prompts, tagged lyrics, genre templates, troubleshooting). |
| [`source-control`](plugins/source-control) | Skills | Git/GitHub delivery workflow in three skills: `/source-control:commit` (Conventional Commits + Co-Authored-By trailer via safe heredoc mechanics), `/source-control:pull-request` (prep, create, CI monitoring, review-comment triage, merge, multi-PR babysit loop), and `/source-control:worktree` (create/status/cleanup/audit for parallel-session isolation). |

Install one: `/plugin install <plugin-name>@melodic-software`.

Expand Down
12 changes: 12 additions & 0 deletions plugins/source-control/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "source-control",
"version": "0.1.0",
"description": "Git and GitHub delivery workflow: /commit (Conventional Commits + Co-Authored-By trailer via safe heredoc mechanics), /pull-request (prep, create, CI monitoring, review-comment triage, merge, multi-PR babysit loop), and /worktree (create, status, cleanup, audit for parallel-session isolation).",
"author": {
"name": "Melodic Software",
"email": "info@melodicsoftware.com"
},
"license": "MIT",
"keywords": ["git", "github", "commit", "pull-request", "worktree", "ci", "code-review", "delivery", "skill"]
}
98 changes: 98 additions & 0 deletions plugins/source-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# source-control

A Claude Code plugin bundling the git/GitHub delivery workflow as three
composable skills — commit mechanics, the full PR lifecycle, and worktree
lifecycle management.

## Skills

### `/source-control:commit`

Builds a commit the safe way: drafts a **Conventional Commits** subject
(11-type vocabulary, consumer convention wins), pre-checks it against the
pattern before git runs, appends a `Co-Authored-By: Claude …` trailer, and
feeds the message via Bash heredoc (`git commit -F - --cleanup=verbatim`) —
never PowerShell here-strings, never scratch files in `.git/`. Stages
surgically (`git add <path>`, never `-A`), and supports pathspec-limited
commits when the index is shared with a concurrent session.

### `/source-control:pull-request`

Orchestrates the PR lifecycle with two non-negotiable gates — every review
finding is verified before it is presented, and every CI fix is
research-gated:

- **prep** — review the branch diff (via your review agents/skills when
installed, inline otherwise), verify findings, simplify, then run the
project's build+test+lint gate as a hard block.
- **create** — branch-name check, default-branch rebase, unrelated-changes
triage, `Closes #N` derivation from the branch name (validated against the
live issue), safely-assembled PR body, `gh pr create`.
- **monitor** — async event loop over CI checks + review comments. Event
delivery prefers a push channel when your environment ships one, falls back
to a session-persistent Monitor watch (30s `gh` poll), or plain `gh`
polling in cloud sessions. CI failures are read from complete logs via the
bundled annotation/ZIP fetch scripts (`gh run view --log-failed`
truncates); every reviewer comment gets explore → research → classify →
react → reply → fix → verify-on-GitHub treatment.
- **merge** — 6-gate readiness re-verification, squash merge, worktree
reuse/cleanup, post-merge CI health check. Never auto-merges.
- **babysit** — self-pacing all-PR loop (designed for
`/loop /pull-request babysit`): discovers every open PR, checks each out,
processes every finding individually with GitHub-verified evidence, and is
mechanically gated by the bundled `babysit-readiness-gate.sh` (classification
rows must cover source findings before readiness can be declared). Never
merges.
- **fetch-logs** — tiered CI-log retrieval (annotations → full untruncated
ZIP via the REST API → per-job text).

### `/source-control:worktree`

Git worktree lifecycle for parallel-session isolation: `create` (guided
naming, EnterWorktree, post-create setup checks), `status` (porcelain parse,
batched PR cross-reference, staleness classification), `cleanup`
(file-lock-aware removal that never counts a Windows husk as deleted, emits
destructive branch deletion for the user), `audit` (configuration health).

## Works in any repo

- **Self-contained.** Everything runs on `git`, `gh`, and scripts bundled
under `${CLAUDE_PLUGIN_ROOT}`; transient CI-log scratch goes to
`${CLAUDE_PLUGIN_DATA}` (or `mktemp`).
- **Graceful degrade.** Adjacent capabilities — review agents, a simplifier,
a verify skill, a research skill, a work-item tracker, a CI-log-audit
agent, a GitHub-events push channel — are used when your environment
provides them and replaced by inline guidance when absent. No phase blocks
on a missing tool.
- **Reads your conventions, assumes none.** Commit-message convention, branch
naming, PR template, merge style, and bot-identity wrappers come from the
consuming project's own `CLAUDE.md`, rules, and hooks. Defaults (
Conventional Commits, squash merge) apply only when the project declares
nothing.

## Install

```shell
/plugin marketplace add melodic-software/claude-code-plugins
/plugin install source-control@melodic-software
```

## Configuration

No `userConfig`. Optional environment variables:

| Variable | Used by | Effect |
|---|---|---|
| `WORKTREE_STALE_DAYS` | `/worktree status` | Staleness threshold (default 14 days) |
| `BABYSIT_SELF_LOGINS` | babysit readiness gate | Extra posting identities (csv) whose replies count as your classification rows — e.g. a project bot account (default: your `gh api user` login) |
| `FETCH_LOGS_SCRATCH` / `FETCH_LOGS_REPO` / `FETCH_LOGS_MAX_BYTES` | `fetch-logs` | Scratch dir, repo override, size cap for CI-log ZIPs |

## Security

- No hooks, no MCP servers, no telemetry, no outbound network beyond `git`
and `gh` against the repository the session already targets.
- Writes to GitHub (comments, reactions, thread resolution, PR creation,
merge) happen only inside the documented `/pull-request` phases, with the
merge decision always behind a human gate.
- Bundled scripts are read-only against the GitHub API except where the
skill body documents a write.
136 changes: 136 additions & 0 deletions plugins/source-control/skills/commit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
name: commit
description: "Create a git commit with a Conventional Commits subject, a Claude Co-Authored-By trailer, and surgical staging (never `git add -A`), feeding the message to git via Bash heredoc. Use when: 'commit this', 'make a commit', 'commit with message <hint>' — not for push, branch creation, or PR creation (use /pull-request)."
argument-hint: "[message-hint]"
user-invocable: true
---

## Pre-computed context

Current branch: !`git branch --show-current 2>/dev/null || echo "unknown"`
Staged: !`git diff --cached --stat 2>/dev/null | tail -1 || echo "nothing staged"`
Unstaged: !`git status --short 2>/dev/null | head -20 || echo "clean"`
Recent commits: !`git log --oneline -5 2>/dev/null || echo "no commits"`

## Purpose

Encapsulates the canonical mechanic for building a commit message that honors a Conventional Commits subject convention, appending a `Co-Authored-By:` trailer, and feeding the result to `git commit` via stdin — without these failure modes:

- **PowerShell here-string syntax (`@'...'@`) inside a Bash tool call** produces `unexpected EOF` and triggers fallback to writing the message to `.git/<TEMP>.txt`. `.git/` is git's internal directory; scratch files there collide with `COMMIT_EDITMSG` and other internals.
- **`git commit -m "<multi-line>"`** flattens newlines unpredictably across shells.
- **`git add -A` / `git add .`** stages secrets, build artifacts, unrelated edits — the convention is surgical staging.

The default subject convention (WHAT shape a subject must take) is **Conventional Commits (11-type vocabulary)**. Every subject must match this anchored pattern:

```text
^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?: .+
```

Compliant examples:

- `feat(auth): add OAuth login flow`
- `fix(api): handle null user in /me endpoint`
- `docs: clarify rebase guidance`
- `refactor(skills)!: rename /simplify to /code-review`

**Consumer convention wins.** If the consuming project's own `CLAUDE.md`, rules, or commit-msg hook declare a different message convention, follow that instead — this skill's pattern is the default, not an override. When the project enforces its convention with a commit-msg git hook (lefthook, husky, commitlint, plain `.git/hooks/`), that hook is the authoritative gate; this skill's pre-check exists to fast-fail client-side before the hook round-trip.

## Task

1. Survey working tree (`git status`, `git diff --cached --stat`) to confirm what's staged.
2. Draft a subject + optional body, scoped to the staged diff, shaped to satisfy the active subject convention (default: the Conventional Commits pattern above).
3. Pre-check the subject against the pattern (fast-fail before invoking git).
4. Invoke `git commit -F -` via the Bash tool, heredoc-piped, with `--trailer` for `Co-Authored-By` per the trailer template below.
5. Surface the resulting commit SHA + subject to the user.

## Canonical bash form

Use the **Bash tool**, not the PowerShell tool. Bash heredoc is the canonical form across all platforms (Git Bash, Linux, macOS).

```bash
git commit -F - --cleanup=verbatim \
--trailer "<Co-Authored-By trailer, placeholders filled>" \
<<'EOF'
<subject — shaped to satisfy the active subject convention>

<body — wrap at ~72 cols, blank line between paragraphs>
EOF
```

The `--trailer` argument body is this template:

```text
Co-Authored-By: Claude <model> (<context>) <noreply@anthropic.com>
```

Fill the `<model>` / `<context>` placeholders from session knowledge before passing the string to `--trailer` (see "Trailer model + context lookup" below).

PowerShell here-string is shown only for reference — `git commit -F - <message-via-stdin>` with `@'...'@` would work in a pure PowerShell tool call, but **never mix syntaxes inside one tool invocation**. A PowerShell `@'...'@` block inside a Bash tool call leaves the bash parser unable to terminate the heredoc.

**Hard rules:**

- Invoke via the **Bash tool**.
- Heredoc delimiter is single-quoted: `<<'EOF' ... EOF`. Single quotes prevent `$variable` and backtick interpolation inside the message.
- `--cleanup=verbatim` preserves the message exactly — no auto-stripping of comments or whitespace.
- Never write the message to `.git/<TEMP>.txt`. If a real file is unavoidable, use `mktemp`.
- Never mix Bash heredoc with PowerShell `@'...'@` inside one invocation.

## Pre-check

Before invoking `git commit`, regex-match the drafted subject against the active convention's pattern (default: the Conventional Commits pattern above).

On mismatch, surface the convention name and the compliant examples as actionable guidance, and ask for a compliant subject before invoking git. The pre-check is shape-only; the project's `commit-msg` git hook (when one exists) is the authoritative gate at commit time. The pre-check exists to save the hook-startup floor when the drafted subject is obviously wrong, plus to give the user a fast actionable error rather than an opaque hook failure.

## Trailer model + context lookup

The trailer body is `Co-Authored-By: Claude <model> (<context>) <noreply@anthropic.com>`. Fill the `<model>` and `<context>` placeholders from your own knowledge of the running session — e.g. model = `Opus 4.8` or `Fable 5`, context = `1M context`. If uncertain, invoke `/usage` to confirm before committing.

There is no environment variable that auto-fills these — the trailer is part of the message body sent to `git commit`, not git config. Hardcoding stale values is worse than asking; the trailer becomes a git-history claim about which model / context authored the change. If the consuming project's conventions specify a different attribution trailer (or none), follow those.

## Unrelated uncommitted changes

If the working tree contains unstaged or untracked files that fall outside this commit's scope, classify each before staging per `/pull-request create` (its unrelated-changes classification: include / stash / separate-commit / discard). Do not duplicate that classification here; invoke `/pull-request create` to surface it to the user.

## Staging discipline

Always `git add <specific-files>`, never `git add -A` or `git add .`. The risk is including secrets, build artifacts, or unrelated changes that the user did not approve for this commit. If multiple files are intentionally part of the commit, stage them by explicit list, not by wildcard.

## Pathspec-limited commits (dirty shared index)

When the index already holds staged files OUTSIDE this commit's scope — concurrent Claude Code sessions on the same branch, pre-existing mixed WIP — a bare `git commit` would sweep them all in. Instead, limit the commit by pathspec:

```bash
git commit -F - --cleanup=verbatim \
--trailer "<Co-Authored-By trailer>" \
-- <path> [<path>...] <<'EOF'
<subject>

<body>
EOF
```

Semantics (per `git-commit(1)` default `--only` mode): the commit records the **working-tree content** of the named paths, disregarding what is staged for all OTHER paths — concurrent-session staged work stays staged, untouched. Untracked files still need `git add` first; pathspec alone never picks them up.

**Safety preconditions — all required before offering this path:**

- Every named path is fully this commit's work — no overlap with another session's in-flight scope (when unsure which session owns a file, ask).
- For each named path, working tree == intended content (pathspec commits the worktree version, silently superseding any different staged version of that same path).
- Verify scope with `git diff --cached --stat -- <pathspec>` and surface that stat in the review gate — the user greenlights exactly what the pathspec captures.
- A directory pathspec (`-- path/to/dir/`) is acceptable only after confirming via `git status --porcelain -- <dir>` that nothing under it belongs to another scope; otherwise enumerate files.

Default remains the plain index commit; reach for the pathspec form only when the index is verifiably shared/dirty.

## Composition policy

This skill is the single source of truth for the commit mechanic. Other skills should compose `/commit` by natural-language reference rather than invoking `git commit` directly — direct calls bypass the pre-check, trailer logic, and surgical-staging discipline this skill exists to enforce.

Workflow skills without explicit commit semantics should report status at phase boundaries and let the user or the next workflow stage decide commit timing; a skill with commit semantics in its documented contract (e.g. `/pull-request create`) composes this one.

## What this skill does NOT do

- **No `git push`** — that's `/pull-request create`.
- **No branch creation** — that's the project's branch-naming / branch-protection mechanisms (or `/worktree create`).
- **No PR body composition** — that's `/pull-request create`.
- **No `git merge` / `gh pr merge`** — that's `/pull-request merge`.
- **No rebase** — that's `/pull-request create`.
- **No `--no-verify` or hook bypass** — if the project's `commit-msg` hook rejects the message, surface the error and re-draft; never bypass.
Loading
Loading