kramme-cc-workflow/skills/kramme:git:fixup/SKILL.md
Intelligently fixup unstaged changes into existing commits on the current branch. Maps each changed file to its most recent commit, validates (build/test/lint), creates fixup commits, and autosquashes.
npx skillsauth add abildtoft/kramme-cc-workflow kramme:git:fixupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Intelligently fixup unstaged changes into existing commits on the current branch, with validation.
Before proceeding with the workflow, check if the user provided additional instructions after the command:
Parse arguments and instructions — If the user wrote /kramme:git:fixup <something>:
--skip-tests, --skip-build, --skip-lint, --skip-all, --no-confirm, --base=<branch>)Apply custom instructions throughout — If the user provided instructions, keep them in mind when:
Examples of custom instructions:
Detect base branch:
Try these methods in order:
Check origin/HEAD (most reliable - reflects remote's default branch):
git symbolic-ref refs/remotes/origin/HEAD 2> /dev/null | sed 's@^refs/remotes/origin/@@'
If that fails, check if main branch exists locally:
git show-ref --verify --quiet refs/heads/main
If that fails, check if master branch exists locally:
git show-ref --verify --quiet refs/heads/master
If none work, fail with a clear error:
"Could not auto-detect base branch. Use
--base=<branch>to specify. Rungit branchto see available branches."
Store the resolved branch name as BASE_BRANCH. The --base=<branch> option always overrides auto-detection.
Check branch rewrite safety:
Confirm HEAD is attached to a feature branch before any history-rewriting work:
CURRENT_BRANCH=$(git symbolic-ref --quiet --short HEAD) || {
echo "HEAD is detached; switch to the feature branch before running fixup."
exit 1
}
If $CURRENT_BRANCH is the resolved base branch, abort:
if [ "$CURRENT_BRANCH" = "$BASE_BRANCH" ]; then
echo "Current branch is the base branch '$BASE_BRANCH'; fixup rewrites feature-branch history only."
exit 1
fi
Check whether the upstream tracking branch has commits that are not in local HEAD:
UPSTREAM=$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)
UPSTREAM_REWRITE_WARNING=0
if [ -n "$UPSTREAM" ] && git rev-parse --verify --quiet "$UPSTREAM" >/dev/null; then
if ! git merge-base --is-ancestor "$UPSTREAM" HEAD; then
echo "Upstream '$UPSTREAM' is ahead of or diverged from local HEAD; autosquash would rewrite shared history."
UPSTREAM_REWRITE_WARNING=1
fi
fi
If UPSTREAM_REWRITE_WARNING=1, treat it as a stop-and-confirm moment: ask whether collaborators are coordinated and whether to proceed with rewriting local branch history. Under --no-confirm, abort instead of asking.
Check for staged changes:
git diff --cached --name-only
If staged changes exist, ask the user whether to:
Under --no-confirm, include staged changes automatically (the most common intent for an unattended run).
If including staged changes, unstage them first (git reset HEAD <files>) so they flow through the normal mapping process.
Check for unstaged and untracked changes:
Detect tracked changes (with rename detection) and untracked files separately — git diff alone omits untracked files:
git diff --name-status -M # tracked: modified (M), deleted (D), renamed (R)
git ls-files --others --exclude-standard # untracked (new) files
Untracked files have no commit that touched them, so they are always orphans (Step 3b) — they cannot be fixed up.
If there is nothing to process (no tracked changes, no untracked files, and no staged changes being included), inform the user and exit.
Check branch has commits ahead of base:
git log --oneline <base>..HEAD
If no commits, inform user this command requires existing commits to fixup into.
Check for merge commits on the branch:
git log --merges --oneline <base>..HEAD
If non-empty, stop and confirm with the user before proceeding: the autosquash rebase in Step 5 (GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash) silently linearizes merge commits, rewriting the branch topology. Under --no-confirm, abort. (Preserving merges via --rebase-merges is out of scope for this skill.)
Check for leftover fixup commits:
git log <base>..HEAD --oneline --grep '^fixup!'
Pre-existing fixup! commits usually mean a prior run created fixups but did not finish the autosquash rebase. Ask the user whether to resume the autosquash now (skip to Step 5) or abort so they can inspect. Under --no-confirm, resume the autosquash.
Before creating any commits, validate the changes won't break the build.
IMPORTANT: Reference the project's AGENTS.md, CLAUDE.md, or equivalent instruction files to find the correct commands for:
Run validations scoped to the changed files:
Use check-only commands (e.g., lint not lint --fix, format:check not format) to avoid modifying files mid-workflow.
If validation finds issues, ask the user:
Under --no-confirm, abort on validation failure — never rewrite history over failing checks unattended.
Do NOT silently proceed with validation failures.
For each changed file (modified, deleted, or renamed), find which commit on the branch most recently touched it:
git log <base>..HEAD --oneline -- <file_path>
Take the first (most recent) commit from the output as the target for that file.
Note: Deleted files work the same way - they get fixed up into the commit that originally added/modified them. If a file was added and is now being deleted, the fixup will remove it from that commit entirely (as if it was never added).
Renamed files: Map using the file's pre-rename (old) path from git diff --name-status -M, since the new path has no history yet. The rename targets whichever commit last touched the original path. If only the new path is known, treat it as an orphan.
Untracked files: These have no matching commit and are always listed under orphans below.
Create a mapping and present everything in one view:
Fixup Plan (base: main):
Matched files:
→ abc1234 "Add feature X"
- src/file1.ts (modified)
- src/helper.ts (deleted)
→ def5678 "Fix bug Y"
- src/file3.ts (modified)
⚠ Orphan files (no matching commit):
- src/newfile.ts
- src/unrelated.ts
These orphan files were not modified by any commit on this branch.
They cannot be fixed up and will need a separate commit.
If orphan files exist, ask the user to decide:
Why this happens:
Options:
When --no-confirm is set, orphan files are automatically skipped.
For each target commit, stage the relevant files and create a fixup commit:
git add <files...>
git commit --fixup=<commit_sha>
Run an autosquash rebase to squash fixup commits into their targets. Use the branch fork point (merge-base) so this rewrites only branch commits and does not pull newer base-branch commits into the feature branch:
FORK_POINT=$(git merge-base HEAD <base>)
GIT_SEQUENCE_EDITOR=true git rebase -i --autosquash "$FORK_POINT"
If the rebase succeeds, proceed to Step 6.
If the rebase fails (conflicts), see Error Handling below.
If REVIEW_OVERVIEW.md (produced by the kramme:pr:code-review skill) exists in the project root:
**Commit:** field with the short hash of the commit containing the fixREVIEW_OVERVIEW.md is a working document for tracking review responses; it should never be committedShow the final commit log:
git log --oneline <base>..HEAD
Confirm success and show any remaining unstaged/untracked files.
Remind user: If this branch was already pushed, they'll need to force push:
git push --force-with-lease
.git/index.lock may be stale, or it may be held by a running git process — deleting it while a process is active can corrupt the index. Do not remove it blindly:
.git/index.lock, then retry once. Under --no-confirm, abort instead of deleting — never remove a lock file unattended (consistent with never rewriting history over failing checks unattended).Stop immediately. Do not create any commits. Report the specific failures.
If the rebase fails mid-way due to conflicts:
Detect failure: Check exit code of rebase command, or check if .git/rebase-merge directory exists.
Abort automatically: Run git rebase --abort to restore the branch to its pre-rebase state.
Inform user clearly:
"Rebase failed due to conflicts between fixup changes and target commit."
"The branch has been restored to its pre-rebase state."
"Your fixup commits are NOT lost - they still exist on the branch."
Provide resolution options:
git rebase -i --autosquash "$(git merge-base HEAD <base>)" and resolve conflicts themselvesgit reset HEAD~N (where N = number of fixup commits created)fixup! commits in Step 1 and offers to resume the autosquash, instead of finding no unstaged changes and silently exitingArguments: $ARGUMENTS
Flags:
--skip-tests - Skip running tests (use when you've already validated)--skip-build - Skip build validation--skip-lint - Skip lint/format validation--skip-all - Skip all validations--no-confirm - Skip confirmation prompts. Defaults: staged changes are included, orphan files are skipped, validation failures abort, merge commits on the branch abort, stale lock files abort, and leftover fixup commits are autosquashed.--base=<branch> - Override auto-detected base branchCustom Instructions: Any text after the command (and flags) is treated as custom instructions that influence the workflow. These instructions are applied contextually throughout the process.
# Standard usage - auto-detect base, validate and fixup
/kramme:git:fixup
# Skip all validations (already tested manually)
/kramme:git:fixup --skip-all
# Skip only tests
/kramme:git:fixup --skip-tests
# Explicit base branch
/kramme:git:fixup --base=develop
# Non-interactive (for scripting)
/kramme:git:fixup --skip-all --no-confirm
# With custom instructions
/kramme:git:fixup Only process the API controller changes
/kramme:git:fixup --skip-tests Focus on the frontend, ignore backend files
/kramme:git:fixup Group related changes together even if they touched different commits
origin/HEAD, then main, then master--base=<branch> to specify explicitly--no-confirm)--no-confirmAGENTS.md, CLAUDE.md, or equivalent instruction filesREVIEW_OVERVIEW.md exists in the project root, this skill updates its **Commit:** fields in place (never committing the file); otherwise that step is skippeddevelopment
Runs kramme:pr:code-review as a closeout review loop for local or PR branch changes before commit, ship, or final response. Use when the user asks for autoreview, second-model review, or a final code-review pass after non-trivial edits. Not for UX, visual, accessibility, or product review.
development
Guides topic-level understanding verification for a PR, branch, feature, document, spec, design decision, bug fix, or other concrete subject. Use when the user asks to confirm, quiz, drill, teach-and-check, or verify that they understand a topic. Maintains a topic-specific checklist artifact and requires demonstrated understanding before marking the topic complete. Not for ordinary explanations without verification, end-of-session summaries, or code/test correctness checks.
testing
Design a CI/CD pipeline with quality gates, a <10-minute budget, feature-flag lifecycle, and an exit checklist. Use when adding a new CI pipeline, changing gate configuration, or planning a rollout for a new service. Complementary to kramme:pr:fix-ci (which fixes failures in an existing pipeline). Covers gate ordering, secrets storage, branch protection, rollback mechanism, and staged-rollout guardrails — not a rollout-execution runbook.
tools
--- name: kramme:visual:demo-reel description: Capture local demo evidence for observable product behavior: screenshots, before/after image sets, browser reels, terminal recordings, and short GIF/video proof. Use when shipping UI changes, CLI features, or any change where PR reviewers would benefit from visual or behavioral evidence. argument-hint: "[what to capture] [--url <url>|auto] [--tier static|before-after|browser-reel|terminal-recording]" disable-model-invocation: true user-invocable: tr