Install
$ agentstack add skill-furedea-agent-harness-git-commit-split ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Mode argument from slash-command invocation (empty if none was passed): $ARGUMENTS
/git-commit-split custom command
This command is for a dirty working tree that already contains multiple uncommitted intents. It inspects everything pending, proposes a split plan, waits for approval, then lands one commit per approved intent. Optionally each commit can be packaged into its own branch and PR.
Day-to-day implementation workflow belongs to git-workflow. Do not use this command as the default answer to a normal "implement/fix/refactor" request.
The work happens in four phases: mode → inspect → plan → execute. This file owns mode/inspect/plan and routes execute to a mode-specific reference. Show the plan and wait for explicit user approval before any branch or commit lands.
Files in this command
references/hunk_split.md: zero-context partial-apply technique — read whenever a commit splits one file's hunks across commits, in either mode.references/direct_execute.md: Phase 3 fordirectmode.references/pr_per_feature_execute.md: Phase 3 forpr-per-featuremode (covers bothindependentandstack).scripts/build_partial_patch.py: filter a unified diff to a subset of hunks.scripts/branch_name.py: generate a kebab-case branch slug from a Conventional Commits subject, with optional collision avoidance against local +origin.
Phase 0 — Mode selection
The first decision is where the commits will live. There are exactly two delivery modes:
| mode | meaning | | --- | --- | | direct | Commit on the current branch. No branch creation, no push, no PR. Best when you're already on a feature branch, or when the repo has no protections on the current branch. | | pr-per-feature | Create one branch + one PR per commit. Within this mode, the branching strategy is a separate sub-decision presented in the plan: independent (each branch cut from the base, fully parallel PRs) or stack (each branch cut from the previous feature branch, dependent PRs). |
The mode is always set explicitly by the user. Do not auto-detect it. Auto-detection (e.g., probing gh api .../branches/main/protection) is unreliable across environments, silently picks the wrong workflow when authentication is missing, and can push to a protected branch by accident. The cost of asking is one short message; the cost of guessing wrong is a force-push, a denied push that confuses the user, or an unintended PR.
Resolve the mode in this order:
- If this command surfaced a non-empty slash-command argument and it equals
directorpr-per-feature, use that as the mode. Sub-strategy (independent/stack) is not taken from the argument — keep it for the dialog in step 3. If the argument is something else (typo, unrelated text), ignore it and fall through. - Otherwise, if the user's prompt explicitly names the mode (e.g., "PR に分けて", "branch 切って PR", "1 機能 1PR", "stack PR" →
pr-per-feature; "main に直接", "ここで commit", "この branch に commit" →direct), use that. - Otherwise ask one short question and wait. Example phrasing:
> この commit 分割は (a) 現在の branch に直接 commit する direct モードと,(b) 1 機能ごとに branch を切って PR を出す pr-per-feature モード のどちらで進めますか? pr-per-feature の場合は,各 PR を独立に base から切る independent か,順番に積む stack かも併せて教えてください(迷う場合は independent が無難です).
When step 1 already settled the mode as pr-per-feature, ask only the sub-strategy half (independent / stack) instead of repeating the mode question.
- Do not proceed until the user answers (or step 1 already resolved everything needed). Treat silence/ambiguity as "ask again", not "default to direct".
For pr-per-feature, also confirm prerequisites before inspecting:
gh auth status—ghmust be authenticated. Ifghis missing entirely (e.g., a Claude.ai sandbox or a minimal container) or unauthenticated, surface the failure and stop. Don't fall back todirectsilently — the user pickedpr-per-featurefor a reason. Either ask them to authenticate / installgh, or get explicit confirmation to switch the mode.git remote -v— there must be a push remote (typicallyorigin) that points to a hostghunderstands. If absent, stop and report.- Identify the base branch (default branch of the remote) with
gh repo view --json defaultBranchRef -q .defaultBranchRef.name. This is the PR target forindependent, and the cut point of the first branch instack. Record it as ``.
Phase 1 — Inspect
Read every pending change before grouping. Skipping this leads to surface-level groupings ("commit each file") that miss the intent.
git rev-parse --is-inside-work-tree # bail early if not in a repo
git rev-parse --abbrev-ref HEAD # note current branch
git status --porcelain=v1 # tracked + untracked, machine-readable
git diff # unstaged tracked changes
git diff --staged # already-staged changes
For each file in git status:
- Modified (
M/M) — read the diff hunks. - Untracked (
??) — read the file content withRead. If it's small and clearly one feature, plan to add it whole; if it's large and mixes concerns, rungit add -Nso it appears ingit diffand can be hunk-split. - Deleted (
D/D) — note as a deletion; usually pairs with whatever feature removed it. - Renamed/Copied (
R/C) — keep the rename atomic (don't split a rename across commits).
Do not summarize prematurely. Read the actual changes — names, signatures, behavior — so the grouping reflects what the code does, not what the filenames suggest.
Phase 2 — Plan
Group hunks into commits by intent, not by file. Use git-workflow for the shared commit granularity, Conventional Commits, and branch naming rules. This command adds the dirty-tree-specific planning details: which hunks/files belong to each commit, which mode will execute them, and what branch/PR shape will be created in pr-per-feature.
How to group
- Apply
git-workflow's commit granularity rules first. - When one file contains multiple intents, split it by hunk; see
references/hunk_split.md. - Keep generated files, lockfiles, and tests with the intent that caused them unless the existing repo history clearly uses a different convention.
- Do not fabricate splits when the dirty tree is genuinely one cohesive change.
Branch / PR plan (only for pr-per-feature)
When the mode is pr-per-feature, the commit grouping is only half the plan. The user also needs to see and approve:
- Branch strategy —
independentorstack. Recommendindependentunless the commits build on each other in a way the reviewer needs to follow in order (e.g., commit 2 is a refactor that commit 3 depends on). When in doubt, proposeindependentand explain thatstackis available if dependencies matter. - Branch names — generated by
scripts/branch_name.pyfrom each commit subject, followinggit-workflow's branch format. If a name already exists locally or remotely, the script appends-2,-3, …; surface any collision in the plan. - PR base — for
independent, every PR targets `(the remote default branch). Forstack, PRntargets the branch from PRn-1; PR 1 targets`. - PR shape — every PR is created as a normal PR via
gh pr create -f --base(-f= fill title/body from the commit).
Plan presentation
Show the plan as a numbered list, in the order the commits will land. For each commit include the message, the affected files, and — for hunk-split commits — the line ranges or a one-line summary of which hunks. For pr-per-feature, also include the branch name and PR base for each entry, and state the branch strategy and base branch up front. Then ask for approval.
direct example:
Mode: direct (commits land on current branch `feature/big-batch`)
Proposed commits (3):
1. feat(auth): add JWT refresh-token rotation
- src/auth/refresh.ts (new file)
- src/auth/login.ts (hunks 1-2: wire refresh into login)
- tests/auth/refresh.test.ts (new file)
2. fix(parser): handle empty input without panicking
- src/parser/index.ts (hunk 3 only)
3. docs: note refresh-token flow in README
- README.md
Apply this plan? (yes / edit / cancel)
pr-per-feature example:
Mode: pr-per-feature
Strategy: independent (each PR cut from `main`, no dependencies)
Base branch: main
PR shape: normal (gh pr create -f)
Proposed commits / branches (3):
1. feat(auth): add JWT refresh-token rotation
branch: feat/jwt-refresh-rotation → PR base: main
- src/auth/refresh.ts (new file)
- src/auth/login.ts (hunks 1-2)
- tests/auth/refresh.test.ts (new file)
2. fix(parser): handle empty input without panicking
branch: fix/parser-empty-input → PR base: main
- src/parser/index.ts (hunk 3 only)
3. docs: note refresh-token flow in README
branch: docs/refresh-token-readme → PR base: main
- README.md
Apply this plan? (yes / edit / cancel)
For stack, replace the strategy line and the per-entry PR base accordingly:
Strategy: stack (each PR depends on the previous; merge in order)
1. ... branch: refactor/extract-query-builder → PR base: main
2. ... branch: feat/repository-cache → PR base: refactor/extract-query-builder
3. ... branch: test/repository-cache-edges → PR base: feat/repository-cache
If the user requests edits, revise and re-present — never silently change the plan. Treat branch-strategy changes (independent ↔ stack) as a full re-plan; a stack and a parallel set are very different review experiences.
Phase 3 — Execute (router)
Once the user approves, switch to the reference for the chosen mode and follow it end-to-end:
direct→ readreferences/direct_execute.mdpr-per-feature→ readreferences/pr_per_feature_execute.md
Both modes share the hunk-level partial-apply technique in references/hunk_split.md; load it once when the loop first hits a hunk-split commit.
The key invariant for both modes: after each commit, regenerate the diff against the new HEAD before building the next partial patch, because line numbers shift as commits land. The mode-specific references repeat this where it matters.
Edge cases (mode-independent)
These apply regardless of mode. Mode-specific edge cases live in each *_execute.md.
- Nothing to commit. If
git statusis clean before starting, say so and stop. Don't invent commits. - Merge in progress (
.git/MERGE_HEADexists). Don't try to split — the user is mid-merge. Surface this and ask. - Submodule pointer changes. Treat as a single file; usually goes in a
chore(submodule):or with the feature that bumped it. - Binary files. No hunk-level split possible — commit whole or skip.
- User commits in non-English. Follow the language rule in
git-workflow. Branch names stay ASCII because some hosts and tools choke on non-ASCII refs.
Navigation map (read-on-demand)
- Phase 3 (execute),
directmode:references/direct_execute.md - Phase 3 (execute),
pr-per-featuremode (independent or stack):references/pr_per_feature_execute.md - Hunk-level partial apply (any mode, when one file's hunks split across commits):
references/hunk_split.md - Generate a kebab-case branch slug from a commit subject (with collision avoidance):
scripts/branch_name.py - Filter a unified diff to a subset of hunks:
scripts/build_partial_patch.py
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: furedea
- Source: furedea/agent-harness
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.