From code-forge
Use when implementation is complete and you need to merge, create a PR, or clean up β verifies tests pass, presents 4 structured integration options, executes chosen workflow, and cleans up worktrees. Pairs with code-forge:worktree.
npx claudepluginhub tercel/tercel-claude-plugins --plugin code-forgeThis skill uses the workspace's default tool permissions.
@../shared/execution-entrypoint.md
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
@../shared/execution-entrypoint.md
For this skill: start at Step 1 (Verify Tests), then Step 1.5. If you catch yourself about to say "falling back to manual finish", STOP and go to the indicated step.
Complete a development branch by verifying tests, choosing an integration strategy, and cleaning up.
Verify Tests β Simplification Gate β Determine Base Branch β Present 4 Options β Execute Choice β Cleanup Worktree
Run the full test suite before proceeding (following the code-forge:verify discipline β run fresh, read full output, confirm zero failures).
# Auto-detect and run test command
This step is mandatory and runs on every /code-forge:finish invocation. It is the last line of defense against merging bloated, redundant, or dead code that slipped past the planner and the reviewer. Skill-driven feature work has a strong additive bias β this gate is what keeps the codebase from growing unbounded across feature cycles.
The gate is fully self-contained β it does not depend on any external skill. The detection criteria, fix rules, and safety constraints are all defined inline below.
# Determine base branch
BASE_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null | sed 's|origin/||' || echo "main")
# List files changed since branching from base
git diff --name-only "${BASE_BRANCH}...HEAD"
If the changed file list is empty (nothing to merge), skip the gate and proceed to Step 2.
Before running the gate, capture the working-tree state so we can distinguish simplification changes from any other uncommitted changes the user may have:
git status --porcelain > /tmp/code-forge-finish-pre-gate-status.txt
If /tmp/code-forge-finish-pre-gate-status.txt is non-empty (the user already has uncommitted work before the gate runs), display a warning and use AskUserQuestion:
git stash push -u -m "code-forge-finish-pre-gate", then proceed; pop the stash before exiting Step 1.5/code-forge:finishOffload to a sub-agent so the full diff, grep output, and file reads stay out of the main context.
Spawn an Agent tool call with:
subagent_type: "general-purpose"description: "Pre-merge simplification gate"Sub-agent prompt must include all of the following, verbatim, plus the base branch name and the changed-file list from 1.5.1:
You are the pre-merge simplification gate for code-forge:finish.
Your job is to scan the diff between {BASE_BRANCH} and HEAD for bloat introduced by
this branch, fix what is safe to fix automatically, and report the rest. You operate
ONLY on the files listed in CHANGED_FILES below β do not touch anything else.
CHANGED_FILES:
{paste the file list from 1.5.1}
βββ DETECTION CRITERIA βββ
Review every file in CHANGED_FILES against these seven categories. For each finding,
classify it and decide whether you can fix it automatically or whether it needs human
judgment.
(a) DUPLICATE β code in this diff that reimplements something already present elsewhere
in the project. Before flagging, run `Grep` for similar names, similar signatures,
and similar string literals across the project. If a near-equivalent exists, the
new code is a duplicate.
Auto-fix: replace callers of the new symbol with the existing symbol, then delete
the new symbol. Only do this when the existing symbol's behavior is provably
equivalent β otherwise leave for human.
(b) DEAD_CODE β new symbols (functions, classes, types, constants, exports) defined in
the diff that have zero callers anywhere in the project. Use `Grep` across the
full project (not just CHANGED_FILES) to verify there are no external callers.
Auto-fix: delete the symbol and any tests that exist solely for it.
(c) SPECULATIVE_ABSTRACTION β new base classes, interfaces, plugin systems, generics,
factories, or "extension points" introduced with exactly one (or zero) current
call sites. These are added "for future flexibility" but rarely pay off.
Auto-fix: inline back to the concrete implementation if the abstraction has
exactly one caller. Leave for human if it has zero callers (likely related to
DEAD_CODE) or any meaningful subclassing.
(d) WRAPPER β new functions whose entire body is a single call to another function
with the same arguments, or that only rename fields without adding logic.
Auto-fix: inline the wrapper at every call site, delete the wrapper.
(e) SCOPE_CREEP β files, modules, or public APIs introduced by this branch that are
not traceable to any task in the feature's plan.md (look for plan.md under
`planning/{feature_name}/` or `.code-forge/tmp/{feature_name}/`). If no plan.md
exists, skip this category.
Auto-fix: NEVER. Always leave for human β scope decisions are not safe to
automate.
(f) STALE β within CHANGED_FILES, look for unused imports, commented-out code blocks
(β₯ 5 lines), unreachable branches, and TODO/FIXME/HACK comments without
actionable context that this branch touches.
Auto-fix: delete unused imports, delete commented-out blocks, delete unreachable
branches. Leave actionable TODOs alone.
(g) DEFENSIVE β try/except blocks, null checks, or fallbacks that guard scenarios the
type system or upstream invariants already make impossible (e.g., a null check on
a parameter that the type system marks non-nullable, a try/except around a pure
function that cannot raise).
Auto-fix: delete the defensive code. Only do this when you are certain the
guarded scenario is unreachable; otherwise leave for human.
βββ FIX RULES (apply in order) βββ
1. Apply fixes ONLY to files in CHANGED_FILES. Never modify files outside this list,
even if you spot bloat there β surface it as REMAINING_ISSUES instead so the user
can decide whether to expand the scope.
2. Apply DEAD_CODE and STALE fixes first (lowest risk).
3. Then WRAPPER and SPECULATIVE_ABSTRACTION fixes.
4. Then DUPLICATE fixes (highest risk β verify equivalence first).
5. NEVER apply SCOPE_CREEP fixes automatically.
6. After every batch of fixes, re-run the full test suite (auto-detect: pytest |
npx vitest run | go test ./... | cargo test | mvn test | gradle test | dotnet test
| swift test | vendor/bin/phpunit | mix test).
7. If any test fails: identify which fix caused it. Revert ONLY that fix using
`git checkout HEAD -- <specific-file>`. Never use wildcards. Re-run the tests
until they pass. If you cannot isolate the offending fix, revert ALL fixes you
applied in this run (one file at a time, by name) and report the failure.
8. Track every file you modify in `FIXES_APPLIED.file`. The orchestrator uses this
list as the sole source of truth for what to commit or revert β if you forget a
file, the orchestrator will not commit it.
βββ HARD CONSTRAINTS βββ
- Never run `git add -A`, `git checkout -- .`, `git reset --hard`, `git clean`, or
any other wildcard git command. Every git operation must name specific files.
- Never commit, never push, never merge. Leave all surviving fixes uncommitted in
the working tree.
- Never modify a file outside CHANGED_FILES, even to fix something obviously broken.
Report it in REMAINING_ISSUES instead.
- Never delete a file the user authored on this branch unless it is provably dead
(zero callers anywhere, no tests, no exports).
βββ REQUIRED OUTPUT FORMAT βββ
Return exactly the structure defined in "Sub-agent return format" below
(no preamble, no postscript). The orchestrator parses it field by field.
Sub-agent return format:
GATE_REPORT
DIFF_SCOPE:
base: {base_branch}
files_changed: {N}
loc_added: {N}
loc_removed: {N}
FINDINGS:
- severity: critical | warning | suggestion
category: duplicate | dead_code | speculative_abstraction | wrapper | scope_creep | stale | defensive | other
file: {path:line}
detail: {what's wrong}
action: {fixed | needs_human_decision | left_alone}
FIXES_APPLIED:
- file: {path}
category: {category}
description: {what was changed}
TESTS_AFTER_FIX:
status: pass | fail | skipped
passed: {N}
total: {N}
REMAINING_ISSUES:
- {issues that need human decision before merge}
NET_LOC_DELTA: {original loc_added minus lines removed by gate fixes}
Read the report from the sub-agent and act. The set of files the sub-agent touched comes ONLY from FIXES_APPLIED.file in the report β never from git status, never from a wildcard. This isolation is what makes the gate safe to run on a working tree that may also contain unrelated user changes.
Build GATE_FILES = the deduplicated list of file paths from FIXES_APPLIED.file.
No findings, no fixes applied (FIXES_APPLIED is empty): Display Simplification gate: clean. No bloat detected. If we stashed in 1.5.2, git stash pop. Proceed to Step 2.
Fixes applied, all tests still pass: Display the FIXES_APPLIED list and the new NET_LOC_DELTA. Use AskUserQuestion to ask:
git diff -- $GATE_FILES (only the gate files), display the summary, then re-ask the same question.git add -- $GATE_FILES. Then commit: git commit -m "chore: pre-merge simplification gate". If the gate was preceded by a stash (1.5.2), git stash pop AFTER the commit so the user's prior work returns to the working tree unmixed with the gate commit. Proceed to Step 2.AskUserQuestion to confirm with a separate "Yes, discard" / "Cancel" choice. On confirmation, revert ONLY the gate files: git checkout HEAD -- $GATE_FILES. Never run git checkout -- . or git reset --hard β those would destroy unrelated user changes. If we stashed in 1.5.2, git stash pop. Proceed to Step 2.Tests broke after fixes (sub-agent should have already reverted the offending fix): Display the failing test name, the reverted fix, and the remaining FIXES_APPLIED entries. STOP. Do not proceed to Step 2. The user must verify the working tree manually and re-run /code-forge:finish.
REMAINING_ISSUES is non-empty (unfixable bloat that needs human judgment): Display them with file:line references. Use AskUserQuestion:
Hard rule: The simplification gate is never silently skipped. Even if the diff is small. Even if the user is in a hurry. Skipping requires the explicit user choice "Proceed to merge options anyway". And under no circumstance does the gate use destructive wildcard git commands (git checkout -- ., git reset --hard, git add -A, git clean) β every operation is scoped to GATE_FILES.
# Find the upstream branch this was created from
BASE_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null | sed 's|origin/||' || echo "main")
Present these options to the user using AskUserQuestion. Do NOT modify, add, or remove options:
Option 1: Merge back to {base-branch} locally
git checkout {base-branch} && git merge {feature-branch}Option 2: Push and create Pull Request
git push -u origin {feature-branch} then gh pr createOption 3: Keep branch as-is
Option 4: Discard this work
Option 1 β Merge:
# If inside a worktree, cd to the main repo first
MAIN_REPO=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel 2>/dev/null)
if [ -n "$MAIN_REPO" ] && [ "$MAIN_REPO" != "$(git rev-parse --show-toplevel)" ]; then
cd "$MAIN_REPO"
fi
git checkout {base-branch}
git merge {feature-branch} --no-ff
Option 2 β Push + PR:
git push -u origin {feature-branch}
gh pr create --title "{feature-name}: <summary>" --body "$(cat <<'EOF'
## Summary
<generated from commits>
## Test plan
- [ ] All tests pass
Generated with [code-forge](https://github.com/anthropics/claude-code)
EOF
)"
Report the PR URL to the user.
Option 3 β Keep: No action. Report current branch and worktree location.
Option 4 β Discard: Ask user to type "discard" to confirm. Then:
git checkout {base-branch}
git branch -D {feature-branch}
Options 1, 2, 4: Detect if inside a worktree and remove it:
# Detect worktree: if git-common-dir differs from git-dir, we are in a worktree
COMMON_DIR=$(git rev-parse --git-common-dir 2>/dev/null)
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
if [ "$COMMON_DIR" != "$GIT_DIR" ]; then
WORKTREE_PATH=$(pwd)
cd $(git -C "$COMMON_DIR/.." rev-parse --show-toplevel)
git worktree remove "$WORKTREE_PATH"
fi
Option 3: Do NOT clean up. The worktree stays.
If the feature's plan was stored in .code-forge/tmp/ (created with --tmp):
.code-forge/tmp/{feature_name}/.code-forge/tmp/ is now empty, remove .code-forge/tmp/. If .code-forge/ is also now empty, remove it too.Cleaned up temporary plan files: .code-forge/tmp/{feature_name}/Option 3 (Keep): Do NOT clean up β the tmp plan files stay for future /impl sessions.
Branch finished:
Feature: {feature-name}
Action: {Merged / PR created / Kept / Discarded}
PR URL: {url} (Option 2 only)
Worktree: {removed / preserved}
Tmp plan: {cleaned up / preserved} (only shown for --tmp plans)
$ /code-forge:finish
Tests: 42/42 passing β
How would you like to integrate this branch?
1. Merge back to main locally
2. Push and create Pull Request
3. Keep branch as-is
4. Discard this work
> 2
Branch finished:
Feature: user-auth
Action: PR created
PR URL: https://github.com/org/repo/pull/47
Worktree: removed
git checkout -- ., git add -A, git reset --hard, or any other wildcard git operation in Step 1.5 β every command must be scoped to GATE_FILES (the explicit list returned by the sub-agent in FIXES_APPLIED.file)