| name | git-stage-hunk |
| description | Stage only specific hunks from the working tree for selective commits. Use when a file has changes from multiple sessions, parallel AI agents, or mixed user and agent edits and you need to commit only the changes made by the current session. Use when git add -p is unavailable or when you need non-interactive partial staging. Lists hunks with IDs, stages by hunk ID, file, regex pattern, or line range. |
| argument-hint | [--list [--file PATH] [--split] [--table]] [--hunk H1,H3.1,H5:5-10] [--pattern REGEX] [--file PATH] [--range FILE:S-E] [--verify] [--dry-run] [--table] |
| allowed-tools | AskUserQuestion, Bash |
| user-invocable | true |
git-stage-hunk
Non-interactive hunk staging for selective git add without a TTY. Replaces git add -p in scripted and multi-agent environments. Use when only some changes in a file belong in the current commit, when multiple sessions or agents modified the same file and you need to commit selectively, or when git add -p is unavailable because there is no TTY.
The heavy lifting happens in the Python script. Your first action MUST be Bash - call the script directly, then present the output. Do not re-implement git diff/apply logic yourself.
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --table
Quick workflow
-
List hunks:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --table
-
Stage the ones you want:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --hunk H1,H3 --table
-
Commit, then re-list to see what remains.
WARNING: Hunk IDs shift after staging or committing. Always re-list before using IDs from a previous run.
Filter the listing to one file:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --file src/auth.ts --table
Preprocessed context
Arguments
Parse from $ARGUMENTS:
| Flag | Default | Purpose |
|---|
--list | - | List all unstaged hunks with IDs and previews |
--list --file PATH | - | List hunks filtered to file(s), comma-separated |
--list --split | - | List all hunks with sub-hunk breakdown |
--split H3 | - | Show sub-hunks for one specific hunk |
--hunk H1,H2,... | - | Stage specific hunks by sequential ID |
--hunk H3.1,H3.2 | - | Stage sub-hunks by dot-notation ID |
--hunk H3:5-10 | - | Stage hunk-relative lines 5-10 of H3 |
--pattern REGEX | - | Stage hunks matching regex content |
--file PATH | - | Stage all hunks for file(s), comma-separated |
--range FILE:S-E | - | Stage hunks overlapping line range |
--table | off | Output as markdown table (default is NDJSON) |
--dry-run | off | Preview without applying |
--verify | - | Show staged vs unstaged summary |
Primary workflow: --list then --hunk (see Quick workflow above). Other modes (--pattern, --file, --range) are alternatives for bulk selection.
--file has dual behavior: with --list it filters the listing, without --list it stages all hunks for that file. If no mode flag is provided, default to --list.
Workflow
Phase 1: Setup
- Parse
$ARGUMENTS for mode flags and options.
Phase 2: Dependency check
-
Run the script with --check-deps:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --check-deps
-
Parse the NDJSON output. Each line is a dependency status.
-
If the script exits with code 3 (patchutils missing), use AskUserQuestion:
- Question: "patchutils is not installed. Install it now?"
- Option 1: "Yes, install" - "Full hunk filtering with grepdiff/filterdiff. Most reliable."
- Option 2: "No, use fallback" - "Pure-Python parsing. --pattern and --range modes unavailable."
-
If user chooses install, use the OS value from Preprocessed context:
- Darwin:
brew install patchutils
- Linux:
sudo apt-get install -y patchutils
-
If user chooses fallback, pass --fallback to all subsequent script calls.
-
Read references/patchutils-guide.md for patchutils command reference before advising on installation.
-
If git or python3 are missing, report and stop.
Phase 3: Execute mode
Run the script with the user's requested mode. Always pass --table for human-readable output:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --file src/auth.ts --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --list --split --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --split H3
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --hunk H1,H3 --dry-run --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --hunk H1,H3 --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --hunk H3.1,H3.2 --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --hunk H3:5-10 --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --pattern 'handleAuth' --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --file src/auth.ts --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --range src/auth.ts:45-60 --table
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --verify --table
Add --fallback if the user declined patchutils in Phase 2.
Mixed hunk IDs are supported in a single --hunk call: plain IDs (H1), sub-hunk IDs (H3.2), and line-select IDs (H5:10-15) are processed in separate batches internally.
Phase 4: Present results
With --table, output is already formatted as a markdown table. Present directly.
For NDJSON output (no --table), read references/output-format.md for the schema of each mode.
If the summary includes "fallback":true, note that --pattern and --range modes are unavailable without patchutils.
Phase 5: Verify (optional)
After staging, optionally run --verify to show what ended up staged vs unstaged:
"${CLAUDE_SKILL_DIR}/scripts/git-stage-hunk.py" --verify --table
Hunk ID scheme
Sequential IDs: H1, H2, H3, ... assigned by alphabetical file order, then position within each file. Stable within a single diff snapshot but shift after staging (see warning in Quick workflow).
Sub-hunk IDs
Format: H{parent}.{sub} where parent is the global hunk number and sub is 1-indexed within the parent. Example: H3.1, H3.2, H3.3.
Sub-hunks are derived by re-running the diff with --inter-hunk-context=0 --unified=0 to produce the finest possible hunks, then mapping fine hunks back to their parent's line range.
Sub-hunks are terminal - no recursive splitting. Use line-select (H3:5-10) for finer control within any hunk.
Line-select IDs
Format: H{id}:{start}-{end} where start and end are 1-based line numbers relative to the hunk body (line 1 = first line after the @@ header). Example: H3:5-10.
Read references/split-hunk-guide.md for splitting mechanics, header recalculation, and edge cases.
Error handling
- Empty diff: script outputs
{"error":"no_unstaged_changes"} and exits 0.
- Invalid hunk IDs: script warns about bad IDs, stages valid ones.
- Apply conflicts: script tries bulk apply first, falls back to per-file, then per-hunk. Each result reported individually.
- Index lock: script detects "index.lock" in git apply stderr and emits
{"error":"index_locked"}.
- Binary files: silently skipped during hunk indexing.
- Not splittable:
--split H3 returns {"splittable":false} with suggestion to use line-select. Not an error.
Dependencies
- git (required)
- python3 (required, for
scripts/git-stage-hunk.py and scripts/split_hunk.py)
- patchutils (optional, provides lsdiff/filterdiff/grepdiff)
Read references/patchutils-guide.md for patchutils usage details.
Example invocations
List and inspect hunks:
/git-stage-hunk --list --table
/git-stage-hunk --list --file src/auth.ts --table
/git-stage-hunk --list --split --table
/git-stage-hunk --split H3
Stage by hunk ID (plain, sub-hunk, line-select, mixed):
/git-stage-hunk --hunk H1,H3 --table
/git-stage-hunk --hunk H2 --dry-run --table
/git-stage-hunk --hunk H3.1,H3.2 --table
/git-stage-hunk --hunk H3:5-10 --table
/git-stage-hunk --hunk H1,H3.2,H5:10-15 --table
Bulk selection and verification:
/git-stage-hunk --pattern 'TODO|FIXME' --table
/git-stage-hunk --file src/auth.ts,src/db.ts --table
/git-stage-hunk --range src/auth.ts:45-60 --table
/git-stage-hunk --verify --table