Ring:Committing Changes logo

Ring:Committing Changes

Organization
LerianStudio
ring:committing-changes

Commit changes with scope allowlist enforcement, atomic grouping, GPG-signed conventional commits, and trailer management. Detects the repo's PR-validation scope policy before proposing any message. Use when the user asks to commit or has changes ready to record. Skip when the working tree is clean or the user wants raw git commands without grouping.

Overview

PublisherLerianStudio
Repositoryring
Skill namering:committing-changes
Stars
215
Forks
28
Bundled files
Instructions only
LicenseApache-2.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by LerianStudio on GitHub. Read the source before you install it.

Installation

Install the Ring:Committing Changes AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/LerianStudio/ring.git /tmp/ring
mkdir -p .claude/skills
cp -r /tmp/ring/default/skills/committing-changes .claude/skills/lerianstudio-ring-committing-changes
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ring:Committing Changes in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ring:Committing Changes on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ring:Committing Changes is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Analyze changes, enforce scope policy, group them into coherent atomic commits, and create signed commits following repository conventions. This skill transforms a messy working directory into a clean, logical commit history — with a scope that will actually pass PR validation.

⛔ HARD STOP — READ SCOPE POLICY BEFORE ANYTHING ELSE

The scope is REQUIRED in every commit message. It MUST come from the repo's allowlist.

MUST detect the allowlist in Step 0 before analyzing or drafting any commit message. A commit with an invented or omitted scope will fail PR validation and block the PR.


Step 0 — Detect Scope Policy

Many repos enforce an allowlist of valid scope values via a GitHub Actions workflow. Failing this check blocks the PR, so MUST detect it before proposing any commit message.

0.1 — Locate the policy file

Check in this order:

  1. .github/workflows/pr-validation.yml (primary)
  2. .github/workflows/pr-title.yml
  3. .github/workflows/commitlint.yml
  4. .github/workflows/semantic-pull-request.yml
  5. Root configs: commitlint.config.{js,cjs,mjs,ts}, .commitlintrc*

0.2 — Extract the allowed scope list

Common forms to look for:

FormExample
scopes: block (one per line)Under amannn/action-semantic-pull-request
scopes: a,b,c inlineComma-separated on one line
scope-enum ruleIn commitlint config arrays

Also note any type restrictions — some repos limit types beyond the default Conventional Commits set.

0.3 — Apply the policy

SituationRequired Action
Policy found, scope is clearUse only scopes from the allowlist
Policy found, scope is ambiguousSTOP and ask the user which allowed scope to use
No policy file foundMUST still include a scope — ask the user what scope to use

NEVER omit the scope. NEVER invent a scope not in the allowlist. A bare type: description is FORBIDDEN.

State the policy source and chosen scope to the user before proceeding.


Step 1 — Gather Context

Run in parallel:

bash
git status
git diff
git diff --cached
git log --oneline -10

Step 2 — Analyze and Group Changes

For each changed file determine:

  1. Type: feat, fix, chore, docs, refactor, test, style, perf, ci, build
  2. Scope: from the allowlist resolved in Step 0
  3. Logical group: what other files belong with this change?

Grouping Principles

PrincipleDescription
Feature + TestsImplementation and its tests go together
Config Changespackage.json, tsconfig, etc. grouped separately
DocumentationREADME, docs/ changes grouped together
RefactoringPure refactors (no behavior change) separate
Bug FixesEach fix is atomic with its test

Single vs Multiple Commits

Single commit when:

  • All changes belong to one coherent feature/fix
  • User provides a specific message via argument
  • Changes are minimal and related

Multiple commits when:

  • Changes span different concerns (feature + docs + deps)
  • Mix of features, fixes, and chores
  • Better git history benefits future archaeology

Step 3 — Determine Commit Order

Order matters for bisectability:

  1. Dependencies first — so subsequent commits can use them
  2. Core changes — implementation before consumers
  3. Tests with implementation — keep them atomic
  4. Documentation last — documents the final state

Step 4 — Present Plan and Confirm

MUST get user confirmation before executing.

Proposed Commit Plan:
─────────────────────
Scope policy: .github/workflows/pr-validation.yml → allowed scopes: [api, auth, docs, ci]
Chosen scope: auth

1. feat(auth): add OAuth2 refresh token support
   - src/auth/oauth.ts (modified)
   - src/auth/oauth.test.ts (modified)

2. chore(deps): update authentication dependencies
   - package.json (modified)
   - package-lock.json (modified)

3. docs(docs): update OAuth2 setup guide
   - docs/auth/oauth-setup.md (modified)

Proceed with this plan? [Execute plan / Single commit / Let me review]

Use AskUserQuestion to confirm before proceeding.


Step 5 — Draft Commit Messages

Every commit message MUST follow:

<type>(<scope>): <subject>

<body — optional>
  • Subject: max 50 characters, imperative mood ("add" not "added")
  • Body: wrap at 72 characters, explain motivation/context
  • Scope: REQUIRED, from the allowlist — NEVER omit, NEVER invent

Step 6 — Execute Commits

⛔ HARD STOP — TRAILER RULES

THE MOST COMMON MISTAKE: Putting trailer text INSIDE the -m quotes.

bash
# ❌ WRONG — trailer text is INSIDE the -m quotes
git commit -m "feat(auth): add feature

X-Lerian-Ref: 0x1"

# ✅ CORRECT — --trailer is a SEPARATE argument OUTSIDE quotes
git commit -m "feat(auth): add feature" --trailer "X-Lerian-Ref: 0x1"

Before writing ANY git commit command, verify:

  • -m "..." contains ONLY the commit message (no trailer text inside)
  • --trailer flags are OUTSIDE and AFTER the -m parameter
  • Command is structured as: git commit -S -m "msg" --trailer "key: value"

Required Command Structure

bash
git commit -S \
  -m "<type>(<scope>): <subject>" \
  -m "<body if needed>" \
  --trailer "X-Lerian-Ref: 0x1"

For each commit group, in order:

  1. Stage only the files for this commit:

    bash
    git add <file1> <file2> ...
  2. Create signed commit with trailer:

    bash
    git commit -S \
      -m "<type>(<scope>): <subject>" \
      -m "<body if needed>" \
      --trailer "X-Lerian-Ref: 0x1"

If GPG signing fails: check git config user.signingkey and gpg --list-secret-keys.

If no usable key is found, STOP — do NOT offer an unsigned path. Inform the user:

GPG signing is required. No usable signing key was found.

To proceed:
  1. Generate a key: gpg --gen-key
  2. Configure git:  git config --global user.signingkey <key-id>
  3. Re-run this skill.

Committing without -S is not an option — Step 7 will reject unsigned commits.

MUST wait for the user to configure a key before continuing. NEVER drop -S silently or offer "unsigned" as a fallback.

  1. Repeat for each commit group.

Step 7 — Verify Commits

First, resolve the range ref for verification. $BASE may be provided by an orchestrating skill (e.g., ring:shipping-changes). Resolve in this order:

bash
# 1. Upstream tracking ref (works when branch already has a remote tracking branch)
if git rev-parse @{u} >/dev/null 2>&1; then
  RANGE_REF="@{u}"

# 2. $BASE propagated by the orchestrating skill (e.g., ring:shipping-changes)
elif [ -n "$BASE" ]; then
  RANGE_REF="origin/$BASE"

# 3. Standalone: detect base branch via GitHub API
else
  BASE=$(gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null \
    || git remote show origin 2>/dev/null | grep 'HEAD branch' | awk '{print $NF}')
  RANGE_REF="origin/$BASE"
fi

Then verify every commit in the batch:

bash
git log --oneline "$RANGE_REF..HEAD"

for commit in $(git rev-list "$RANGE_REF..HEAD"); do
  # %G? returns: G=good, U=unknown-validity, X/Y=expired, B=bad, E=missing key, N=no signature
  sig_status=$(git log -1 --format="%G?" "$commit")
  echo "$sig_status" | grep -qE '^[GU]' \
    || { echo "Commit $commit: signature invalid or insufficient (status=$sig_status)"; exit 1; }
  git log -1 --format="%(trailers)" "$commit" | grep -q '^X-Lerian-Ref: ' \
    || { echo "Commit $commit: X-Lerian-Ref trailer missing"; exit 1; }
done

git status

For each commit:

  • Accept G (good) or U (unknown validity). Reject X/Y (expired key), B (bad signature), E (missing key), N (unsigned).
  • If the trailer grep fails → stop and report the missing trailer.

Why U is accepted: U means the commit is cryptographically signed with a valid key, but GPG has not established a trust chain for that key (e.g., the key was not signed by a trusted introducer). This is the normal state for freshly generated keys or keys imported from colleagues without manual trust assignment. The signature itself is valid — it proves authorship. G additionally requires GPG's web-of-trust to vouch for the key identity, which is stricter than needed for commit attribution. Both are acceptable; only unsigned (N), bad (B), missing-key (E), and expired-key (X/Y) commits are rejected.

Note: when called from ring:shipping-changes, $BASE is already resolved in Phase 0 and propagated here — the @{u} and standalone detection paths are only needed for standalone invocations.


Step 8 — Offer Push

After successful commit, ask the user:

javascript
AskUserQuestion({
  questions: [{
    question: "Push commits to remote?",
    header: "Push",
    options: [
      { label: "Yes", description: "Push to current branch" },
      { label: "No", description: "Keep local only" }
    ]
  }]
});

If yes:

bash
# Branch with upstream:
git push

# Branch without upstream:
git push -u origin <current-branch>

Examples

Feature commit

bash
git commit -S \
  -m "feat(auth): add OAuth2 refresh token support" \
  -m "Implements automatic token refresh when access token expires." \
  --trailer "X-Lerian-Ref: 0x1"

Bug fix

bash
git commit -S \
  -m "fix(api): handle null response in user endpoint" \
  --trailer "X-Lerian-Ref: 0x1"

Chore

bash
git commit -S \
  -m "chore(deps): update dependencies to latest versions" \
  --trailer "X-Lerian-Ref: 0x1"

Anti-Patterns (FORBIDDEN)

bash
# ❌ WRONG — no scope
git commit -m "feat: add feature"

# ❌ WRONG — invented scope not in allowlist
git commit -m "feat(custom-scope): add feature"

# ❌ WRONG — trailer text inside -m
git commit -m "feat(auth): add feature

X-Lerian-Ref: 0x1"

# ❌ WRONG — emoji or hashtags in message body
git commit -m "feat(auth): add feature
🤖 Generated with Claude"

# ✅ CORRECT
git commit -S \
  -m "feat(auth): add feature" \
  --trailer "X-Lerian-Ref: 0x1"

Trailer Query Commands

bash
# Find commits with specific trailer value
git log --all --format="%H %s %(trailers:key=X-Lerian-Ref,valueonly)" | grep "0x1"

# Show all trailers for a commit
git log -1 --format="%(trailers)"

When User Provides Message

If the user provides a commit message as an argument:

  1. Use it as the subject/body
  2. Validate it has a scope from the allowlist — if missing, ask which scope to use
  3. Create signed commit with trailer

Anti-Rationalization Table

RationalizationWhy It's WRONGRequired Action
"I'll omit the scope for this one"Every commit MUST carry a scope. A bare type: description fails PR validation.MUST include scope from allowlist
"This scope isn't in the allowlist but it makes sense"Invented scopes fail automated checks. The allowlist exists for a reason.MUST use only allowlist scopes or ask user
"No policy file, so scope is optional"Scope is always required. Without a policy, ask the user which scope to use.MUST ask user for scope if no policy found
"I'll commit everything at once"Mixed changes = messy history, hard to bisect/revert.Analyze and group changes first
"Grouping takes too long"Clean history saves hours of debugging later.Always propose commit plan
"I'll put the trailer text in the message body"--trailer is a GIT FLAG, not message text.Use --trailer "X-Lerian-Ref: 0x1" as separate argument
"I'll skip GPG signing"Unsigned commits fail Step 7 verification. There is no unsigned fallback path — configure a key and retry.MUST stop and instruct user to configure GPG key. NEVER drop -S
"HEREDOC will format trailers correctly"HEREDOC puts everything in the message body.Use --trailer flag, NOT HEREDOC

Frequently asked questions

What does the Ring:Committing Changes AI skill do?

Commit changes with scope allowlist enforcement, atomic grouping, GPG-signed conventional commits, and trailer management. Detects the repo's PR-validation scope policy before proposing any message. Use when the user asks to commit or has changes ready to record. Skip when the working tree is clean or the user wants raw git commands without grouping.

Why use Ring:Committing Changes on TypingMind?

Because you install it once and use it with any model. Ring:Committing Changes is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ring:Committing Changes in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/LerianStudio/ring/tree/main/default/skills/committing-changes. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Ring:Committing Changes?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ring:Committing Changes?

As many as you like. As long as a model supports skills, you can use Ring:Committing Changes with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ring:Committing Changes AI skill free?

Yes. It is published on GitHub by LerianStudio under the Apache-2.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇