Committing Changes
Auto-stage, validate, and commit changes. Pass --push to also push and monitor CI.
Workflow
1. Detect VCS
if jj root 2>/dev/null; then
# USE JJ WORKFLOW
else
# USE GIT WORKFLOW
fi
CRITICAL: Always use -m flag with jj to prevent editor from blocking.
2. Check Branch Safety
Check ./CLAUDE.md and ./.claude/CLAUDE.md for a direct-commits-allowed: true marker. If on a protected branch without it, suggest a feature branch. Cache decisions for future runs.
3. Run Validation
Auto-detect project type and run: format -> lint -> typecheck. Stop on failure.
Prefer the repo's own gate when it has one (make validate in ~/.claude),
otherwise load validating-project.
This step is mandatory on the jj path, not best-effort. jj has no hook system
and does not run git's hooks even in a colocated repo, so .git/hooks/pre-commit
never fires on jj describe / jj commit. Whatever that hook would have caught
is caught here or not at all. On the git path the hook still runs — re-stage once
and retry if it rewrites files (see step 6).
jj fix is not a substitute: it only pipes file content through a tool and keeps
what comes back, so it can carry formatters (ruff format, stylua) but never
report-only checks (ruff check, ty, luacheck, hook tests).
4. Craft Commit Message
Use conventional commits format: type(scope): description
Valid types: feat, fix, refactor, docs, style, perf, test, build, ci, chore.
Choose type from the diff:
- New functionality →
feat - Bug fix →
fix - Code restructuring without behavior change →
refactor - CI/CD config →
ci - Build system, deps →
build - Documentation →
docs
Scope is optional but encouraged for multi-module repos. Keep subject under 50 chars, use imperative mood ("add" not "added"). Focus on the "why" not the "what".
5. Commit
jj workflow (preferred):
jj status && jj diff --stat
jj describe -m "feat: message here"
git workflow (fallback):
git add <specific-files>
git commit -F <scratchpad>/commit-msg.txt
Use the Write tool for commit message files (avoids shell escaping). Write them to the session scratchpad directory given in the environment context — not /tmp. There is no env var for it; substitute the literal path. Handle pre-commit hook failures by re-staging and retrying once.
6. Push (if --push or explicitly requested)
PR-safety gate first. If the branch already has an open PR, check for review activity before pushing anything that rewrites what's there:
gh pr view <branch> --json reviews,comments 2>/dev/null
Plain new commits on top are always safe. But if reviews or comments is non-empty and this push would rewrite already-pushed commits (amended description, squash, rebase), stop and ask Teej — force-pushing detaches review threads from their line anchors. See rules/pr-safety.md.
jj:
jj bookmark set <branch> -r @
jj git push --bookmark <branch>
git:
git push -u origin HEAD
7. Monitor CI (after push)
If .github/workflows/ exists and ci=github-actions in hook output:
uv run ~/.claude/skills/monitoring-ci/ci-monitor.py --branch <branch-name>
Do NOT pre-resolve the SHA and pass --sha. The script resolves it from the bookmark/branch, which is correct under every workflow. Deriving it from @- is wrong whenever @ is the pushed commit (the jj describe -m + jj bookmark set -r @ flow used in step 6 above), and the failure is silent: the monitor watches the previous commit's finished run and a green predecessor reports a false pass. See skills/monitoring-ci/SKILL.md.
Run it with run_in_background: true and tell the user "CI monitor running in
background." That is correct here because this runs in the main conversation,
which stays alive to receive the completion notification. It is not correct
inside the monitoring-ci skill itself, which is a backgrounded fork whose
session ends as soon as the command is launched — see that skill for why.
Error Handling
- Ask user about unknown project permissions
- Stop on protected branch violations
- Auto-fix code quality issues using detected formatters/linters
- Re-stage once if pre-commit hooks fail (git only)
- For jj: use
jj op restoreif something goes wrong
Safety Rules
- Never commit to protected branches without permission
- Use temporary files for all commit message operations
- Stop on merge conflicts
- Check branch protection before making changes