GuidedCoding is a Claude Code skill, /gc, for making a bug fix or a bounded change you can trust, with little of
your attention:
- a test that proves the fix;
- one review pass;
- an outside review by another AI assistant for hard or consequential changes, and on request;
- extra checks only when a change needs them (a live call, a run on another platform);
- a short report.
/gc batch runs a supervised list of such jobs one at a time.
The skill is the guided_coding/ folder. It is a set of instructions for Claude, with no code to
install. Start with guided_coding/SKILL.md.
- Claude Code. If you do not have it yet, follow Anthropic's Claude Code quickstart first.
- Git, unless you install from the ZIP download.
- macOS or Linux. GuidedCoding has been tested on macOS and Linux; it has not been tested on Windows.
The review step uses Claude Code's code-review skill when it is available. To let Claude Code install GuidedCoding with you instead of running the commands yourself, see the website's Quick Start.
Put the repository somewhere, then make a link from your Claude Code skills folder to its guided_coding/ folder.
Open Terminal (on a Mac) or a terminal window (on Linux), paste a whole block, and press Return. The blocks are
complete: copy each one whole, with no editing. They are for bash or zsh, the usual shells. If your shell is csh
or tcsh, type bash first, and exit afterwards. They check before they change anything, and they stop on anything
unexpected. If you set CLAUDE_CONFIG_DIR, they use that folder instead of ~/.claude.
Most people should install GuidedCoding in their home folder, or in a folder where they keep software. This works with any project, including PHENIX. If you develop PHENIX, you can instead install it in your PHENIX installation, next to your PHENIX source code.
To choose the folder: the home-folder and ZIP blocks below put GuidedCoding in ~/guided_coding. To put it
somewhere else, first run this line in the same terminal window, with your folder in place of $HOME/software
(keep the quotes and the /guided_coding at the end), then paste the block:
export GC_DIR="$HOME/software/guided_coding"
The block prints the folder it uses. /gc update and /gc uninstall find the folder by themselves.
Most people: in your home folder, with Git. This puts GuidedCoding in ~/guided_coding (or the folder in
GC_DIR) and registers it. If that folder is already a clone of cctbx/guided_coding on master, it updates it with
git pull instead:
sh <<'END'
SKILLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills"
VERSION=1.4
DIR="${GC_DIR:-$HOME/guided_coding}"
case "$DIR" in /*) ;; *) echo "GC_DIR must be a full path, such as $HOME/software/guided_coding; nothing changed."; exit 1;; esac
echo "GuidedCoding folder: $DIR"
for L in gc guided_coding; do if [ -e "$SKILLS/$L" ] || [ -L "$SKILLS/$L" ]; then echo "$SKILLS/$L already exists; nothing changed:"; ls -l "$SKILLS/$L"; echo "To update or move an existing installation, see Update and If you used the earlier GuidedCoding kit."; exit 1; fi; done
if [ -e "$DIR" ]; then
case "$(git -C "$DIR" remote get-url origin 2>/dev/null)" in https://github.com/cctbx/guided_coding|https://github.com/cctbx/guided_coding.git|[email protected]:cctbx/guided_coding|[email protected]:cctbx/guided_coding.git|ssh://[email protected]/cctbx/guided_coding|ssh://[email protected]/cctbx/guided_coding.git) ;; *) echo "$DIR exists but is not a clone of https://github.com/cctbx/guided_coding; nothing changed."; exit 1;; esac
[ "$(git -C "$DIR" rev-parse --abbrev-ref HEAD)" = master ] || { echo "$DIR is not on the master branch; nothing changed."; exit 1; }
git -C "$DIR" pull --ff-only || { echo "Could not update $DIR; nothing registered."; exit 1; }
else
mkdir -p "$(dirname "$DIR")" && git clone https://github.com/cctbx/guided_coding.git "$DIR" || exit 1
fi
grep -qx "# GuidedCoding (version $VERSION)" "$DIR/guided_coding/SKILL.md" 2>/dev/null || { echo "$DIR/guided_coding/SKILL.md is not GuidedCoding $VERSION (it may be the earlier kit or an older version); nothing registered."; exit 1; }
mkdir -p "$SKILLS" && ln -s "$DIR/guided_coding" "$SKILLS/gc" && ls -l "$SKILLS/gc" && grep -m1 '^# GuidedCoding' "$DIR/guided_coding/SKILL.md" && echo "Done. Next: start a new Claude Code conversation in a project folder and type /gc followed by a small task. For a project you will use regularly, type /gc setup there once (recommended) to save its local defaults."
END
PHENIX developers (optional): in your PHENIX installation. This puts GuidedCoding in the installation's
modules/guided_coding and registers it; if that folder is already a clone of cctbx/guided_coding, it uses it as it
is. The installation is the one $PHENIX names, or else the current folder, which must contain modules. Check
which one first with echo $PHENIX; the block prints the folder it uses. The registration is for your whole
account, so /gc uses this copy even when you work in another PHENIX installation. PHENIX's own update does not
update it yet; run git pull in modules/guided_coding. For a shared installation, use the home-folder block unless
you are allowed to change it.
sh <<'END'
SKILLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills"
VERSION=1.4
ROOT="${PHENIX:-$PWD}"
DIR="$ROOT/modules/guided_coding"
echo "PHENIX installation: $ROOT"
[ -d "$ROOT/modules" ] || { echo "No modules folder in $ROOT. Set up PHENIX in this shell, or cd to the installation folder that contains modules; nothing changed."; exit 1; }
for L in gc guided_coding; do if [ -e "$SKILLS/$L" ] || [ -L "$SKILLS/$L" ]; then
case "$(readlink "$SKILLS/$L")" in */cctbx_project/libtbx/guided_coding|*/cctbx_project/libtbx/guided_coding/) echo "$SKILLS/$L is the earlier GuidedCoding kit; nothing changed. To move from it, use the move block below.";; *) echo "$SKILLS/$L already exists; nothing changed:"; ls -l "$SKILLS/$L"; echo "To move a home-folder installation here, see the line after the move block. To update, see Update.";; esac
exit 1
fi; done
if [ -e "$DIR" ]; then
case "$(git -C "$DIR" remote get-url origin 2>/dev/null)" in https://github.com/cctbx/guided_coding|https://github.com/cctbx/guided_coding.git|[email protected]:cctbx/guided_coding|[email protected]:cctbx/guided_coding.git|ssh://[email protected]/cctbx/guided_coding|ssh://[email protected]/cctbx/guided_coding.git) echo "Using the existing $DIR";; *) echo "$DIR exists but is not a clone of https://github.com/cctbx/guided_coding; nothing changed."; exit 1;; esac
else
git clone https://github.com/cctbx/guided_coding.git "$DIR" || exit 1
fi
grep -qx "# GuidedCoding (version $VERSION)" "$DIR/guided_coding/SKILL.md" 2>/dev/null || { echo "$DIR/guided_coding/SKILL.md is not GuidedCoding $VERSION (it may be the earlier kit or an older version; run git pull there); nothing registered."; exit 1; }
mkdir -p "$SKILLS" && ln -s "$DIR/guided_coding" "$SKILLS/gc" || { echo "Could not register GuidedCoding at $SKILLS/gc; nothing changed."; exit 1; }
echo "Registered $SKILLS/gc -> $DIR/guided_coding (GuidedCoding $VERSION)."
echo "Done. Next: start a new Claude Code conversation in a project folder and type /gc followed by a small task. For a project you will use regularly, type /gc setup there once (recommended) to save its local defaults."
END
Moving from the earlier kit (a gc or guided_coding link into cctbx_project/libtbx/guided_coding)? Use this
block instead. It does the same, and replaces only that registration with the new one (it removes the old link,
which is why Claude Code asks you to approve an rm); if anything fails, it puts the old link back:
sh <<'END'
SKILLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills"
VERSION=1.4
ROOT="${PHENIX:-$PWD}"
DIR="$ROOT/modules/guided_coding"
echo "PHENIX installation: $ROOT"
[ -d "$ROOT/modules" ] || { echo "No modules folder in $ROOT. Set up PHENIX in this shell, or cd to the installation folder that contains modules; nothing changed."; exit 1; }
OLD=""
for L in gc guided_coding; do if [ -e "$SKILLS/$L" ] || [ -L "$SKILLS/$L" ]; then
case "$(readlink "$SKILLS/$L")" in */cctbx_project/libtbx/guided_coding|*/cctbx_project/libtbx/guided_coding/) [ -z "$OLD" ] && OLD="$SKILLS/$L" && continue;; esac
echo "$SKILLS/$L already exists; nothing changed:"; ls -l "$SKILLS/$L"; echo "To move a home-folder installation here, see the line after this block. To update, see Update."; exit 1
fi; done
[ -n "$OLD" ] || { echo "No registration of the earlier kit was found; nothing changed. To install, use the install block above."; exit 1; }
if [ -e "$DIR" ]; then
case "$(git -C "$DIR" remote get-url origin 2>/dev/null)" in https://github.com/cctbx/guided_coding|https://github.com/cctbx/guided_coding.git|[email protected]:cctbx/guided_coding|[email protected]:cctbx/guided_coding.git|ssh://[email protected]/cctbx/guided_coding|ssh://[email protected]/cctbx/guided_coding.git) echo "Using the existing $DIR";; *) echo "$DIR exists but is not a clone of https://github.com/cctbx/guided_coding; nothing changed."; exit 1;; esac
else
git clone https://github.com/cctbx/guided_coding.git "$DIR" || exit 1
fi
grep -qx "# GuidedCoding (version $VERSION)" "$DIR/guided_coding/SKILL.md" 2>/dev/null || { echo "$DIR/guided_coding/SKILL.md is not GuidedCoding $VERSION (it may be the earlier kit or an older version; run git pull there); nothing registered."; exit 1; }
if [ -n "$OLD" ]; then OLDT="$(readlink "$OLD")"; rm "$OLD" || { echo "Could not remove the earlier kit's registration $OLD; nothing changed."; exit 1; }; echo "Removed the earlier kit's registration $OLD (it pointed to $OLDT)."; fi
CREATED=""; mkdir -p "$SKILLS" && ln -s "$DIR/guided_coding" "$SKILLS/gc" && CREATED=1
if [ -z "$CREATED" ] || ! grep -qx "# GuidedCoding (version $VERSION)" "$SKILLS/gc/SKILL.md" 2>/dev/null; then
if [ -n "$CREATED" ] && [ "$(readlink "$SKILLS/gc")" = "$DIR/guided_coding" ]; then rm "$SKILLS/gc"; fi
if [ -n "$OLD" ]; then ln -s "$OLDT" "$OLD" && echo "Restored $OLD."; fi
echo "Could not register GuidedCoding; nothing changed."; exit 1
fi
ls -l "$SKILLS/gc" && grep -m1 '^# GuidedCoding' "$SKILLS/gc/SKILL.md" && echo "Done. Next: start a new Claude Code conversation in a project folder and type /gc followed by a small task. For a project you will use regularly, type /gc setup there once (recommended) to save its local defaults."
END
Already installed in your home folder or another folder? Remove that registration first. This removes only a
gc link that points to a GuidedCoding copy (not the earlier kit, and not one in a PHENIX modules folder), and
prints the command to put it back; the copy stays until you delete it:
L="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/gc"; T="$(readlink "$L" | sed 's:/*$::')"; case "$T" in ""|*/cctbx_project/libtbx/guided_coding|*/modules/guided_coding/guided_coding) echo "$L points to ${T:-nothing}, not a GuidedCoding copy this line moves; nothing removed.";; *) if grep -q '^# GuidedCoding (version' "$T/SKILL.md" 2>/dev/null; then rm "$L" && echo "Removed $L. To put it back: ln -s '$(printf %s "$T" | sed "s/'/'\\\\''/g")' '$(printf %s "$L" | sed "s/'/'\\\\''/g")'"; else echo "$L points to $T, which is not GuidedCoding; nothing removed."; fi;; esac
Without Git: from the ZIP download. Download
guided_coding.zip into your Downloads folder.
To check it against the published
guided_coding.zip.sha256, run this; it
should print guided_coding.zip: OK:
(cd ~/Downloads && curl -fsS https://www.thomasterwilliger.org/guided_coding/guided_coding.zip.sha256 | shasum -a 256 -c)
Then run this.
It unpacks the ZIP into ~/guided_coding (or the folder in GC_DIR) and registers it:
sh <<'END'
SKILLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills"
VERSION=1.4
DIR="${GC_DIR:-$HOME/guided_coding}"
case "$DIR" in /*) ;; *) echo "GC_DIR must be a full path, such as $HOME/software/guided_coding; nothing changed."; exit 1;; esac
echo "GuidedCoding folder: $DIR"
ZIP="$HOME/Downloads/guided_coding.zip"
for L in gc guided_coding; do if [ -e "$SKILLS/$L" ] || [ -L "$SKILLS/$L" ]; then echo "$SKILLS/$L already exists; nothing changed:"; ls -l "$SKILLS/$L"; echo "To update or move an existing installation, see Update and If you used the earlier GuidedCoding kit."; exit 1; fi; done
[ -e "$DIR" ] && { echo "$DIR already exists; nothing changed. To update a ZIP installation, see Update."; exit 1; }
[ -f "$ZIP" ] || { echo "Not found: $ZIP. Download it first. If it was saved under another name, such as 'guided_coding (1).zip', rename it to guided_coding.zip. If Safari unpacked it, turn off Settings > General > Open safe files after downloading, and download it again."; exit 1; }
TMP="$(mktemp -d)" && unzip -q "$ZIP" -d "$TMP" || exit 1
set -- "$TMP"/guided_coding-*
[ $# -eq 1 ] && [ -f "$1/guided_coding/SKILL.md" ] || { echo "Unexpected ZIP contents; nothing changed."; rm -rf "$TMP"; exit 1; }
grep -qx "# GuidedCoding (version $VERSION)" "$1/guided_coding/SKILL.md" 2>/dev/null || { echo "the ZIP's guided_coding/SKILL.md is not GuidedCoding $VERSION (it may be the earlier kit or an older version); nothing registered."; rm -rf "$TMP"; exit 1; }
mkdir -p "$(dirname "$DIR")" && mv "$1" "$DIR" && rmdir "$TMP" && mkdir -p "$SKILLS" && ln -s "$DIR/guided_coding" "$SKILLS/gc" && ls -l "$SKILLS/gc" && grep -m1 '^# GuidedCoding' "$DIR/guided_coding/SKILL.md" && echo "Done. Next: start a new Claude Code conversation in a project folder and type /gc followed by a small task. For a project you will use regularly, type /gc setup there once (recommended) to save its local defaults."
END
Each block ends by showing the link and the version line of the skill it registered,
# GuidedCoding (version 1.4), and what to do next. The blocks register only that version
(VERSION=1.4 in each block).
Then start a new Claude Code conversation in the folder of a software project, and type /gc followed by a small
task (or /gc help for an introduction and the list of commands: setup, batch, history, undo, update,
uninstall). If you plan to use GuidedCoding regularly on that project, run
/gc setup there once (recommended): it saves the project's build and test commands, commit rules and other local
defaults in .claude/GC_NOTES.md. Without it, /gc finds these from the project each time. Installing is once per
computer.
Type /gc update in Claude Code: it says whether a newer version exists, and updates after asking once. By hand: for
an installation made with Git, run git pull in its folder (~/guided_coding, the folder you chose, or
modules/guided_coding in PHENIX; /gc help shows which). A ZIP installation has no Git history. To update it:
- remove the link
gcin your Claude Code skills folder ($CLAUDE_CONFIG_DIR/skillsif you setCLAUDE_CONFIG_DIR, otherwise~/.claude/skills); it is only a link, and removing it deletes nothing else; - rename its folder (
~/guided_coding, or the folder you chose) to keep it as a backup, outside the skills folder, so that only one registration remains (two skills namedgcconflict); - download the new ZIP and run the ZIP block again (after the
GC_DIRline, if you chose a folder).
Type /gc uninstall in Claude Code, or paste this block. It removes GuidedCoding from Claude Code: it removes only
the gc link, so /gc stops working, and deletes nothing. It then tells you where GuidedCoding's files are and
whether they hold anything of yours (changes, other files, commits that are not on GitHub, other branches or
stashes). A copy under a modules folder (modules/guided_coding) may belong to a larger installation such as
PHENIX, and stays. Project notes that /gc setup saved (.claude/GC_NOTES.md in your projects) are kept.
sh <<'END'
L="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/gc"
[ -L "$L" ] || { echo "GuidedCoding is not registered at $L; nothing changed."; exit 1; }
T="$(readlink "$L")"; case "$T" in /*) ;; *) T="$(dirname "$L")/$T";; esac
COPY="$(dirname "$T")"
[ "$(basename "$T")" = guided_coding ] || { echo "$L points to $T, not GuidedCoding; nothing changed."; exit 1; }
if [ -e "$T" ]; then grep -q '^# GuidedCoding' "$T/SKILL.md" 2>/dev/null || { echo "$L points to $T, which is not GuidedCoding; nothing changed."; exit 1; }; fi
unlink "$L" || { echo "Could not remove $L; nothing changed."; exit 1; }
echo "Removed GuidedCoding from Claude Code; /gc stops working in new conversations."
KEEP=""
if [ ! -e "$T" ]; then KEEP="-"
elif [ "$(basename "$(dirname "$COPY")")" = modules ]; then KEEP="phenix"
elif [ -e "$COPY/.git" ]; then
[ -d "$COPY/.git" ] || KEEP="it is a linked Git working folder"
[ -n "$KEEP" ] || case "$(git -C "$COPY" remote get-url origin 2>/dev/null)" in https://github.com/cctbx/guided_coding|https://github.com/cctbx/guided_coding.git|[email protected]:cctbx/guided_coding|[email protected]:cctbx/guided_coding.git|ssh://[email protected]/cctbx/guided_coding|ssh://[email protected]/cctbx/guided_coding.git) ;; *) KEEP="it is not a clone of cctbx/guided_coding";; esac
NC="Git could not check it"
[ -n "$KEEP" ] || { ST="$(git -C "$COPY" status --porcelain --ignored)" || KEEP="$NC"; }
[ -n "$KEEP" ] || [ -z "$ST" ] || KEEP="it has changes or files of its own"
[ -n "$KEEP" ] || { BR="$(git -C "$COPY" for-each-ref --format=x refs/heads)" || KEEP="$NC"; }
[ -n "$KEEP" ] || [ "$BR" = x ] || KEEP="it has more than one branch"
[ -n "$KEEP" ] || { UP="$(git -C "$COPY" log --oneline --branches --not --remotes)" || KEEP="$NC"; }
[ -n "$KEEP" ] || [ -z "$UP" ] || KEEP="it has commits that are not on GitHub"
[ -n "$KEEP" ] || { SL="$(git -C "$COPY" stash list)" || KEEP="$NC"; }
[ -n "$KEEP" ] || [ -z "$SL" ] || KEEP="it has stashed changes"
else
LIST="$(cd "$COPY" && find . ! -type d)" || KEEP="its files could not be listed"
if [ -z "$KEEP" ] && [ ! -f "$COPY/RELEASE.sha256" ]; then KEEP="it has no RELEASE.sha256 to show it is unchanged"; fi
if [ -z "$KEEP" ]; then
WANT="$( (sed 's/^[0-9a-f]* /.\//' "$COPY/RELEASE.sha256"; echo ./RELEASE.sha256) | sort)"
[ "$(printf '%s\n' "$LIST" | sort)" = "$WANT" ] || KEEP="its files do not match the release list"
fi
if [ -z "$KEEP" ]; then
if command -v shasum >/dev/null 2>&1; then SUM="shasum -a 256"; else SUM="sha256sum"; fi
(cd "$COPY" && $SUM -c RELEASE.sha256 >/dev/null 2>&1) || KEEP="some of its files were changed"
fi
fi
if [ "$KEEP" = phenix ]; then echo "Its files stay in $COPY, which is part of a larger installation such as PHENIX."
elif [ -z "$KEEP" ]; then echo "Its files are still in $COPY. They hold nothing of yours; delete that folder if you no longer need it."
elif [ "$KEEP" != "-" ]; then echo "Its files are still in $COPY. Before deleting that folder, note that $KEEP."; fi
echo "Project notes (.claude/GC_NOTES.md in your projects) are kept."
END
To delete GuidedCoding's files too, delete the folder it names: rm -rf <that folder>. Check it first if the
block says it holds something of yours.
In a replay of 37 past bug-fix jobs in PHENIX and cctbx, adding one review pass to plain Claude Code cut missed
program errors per job from 0.81 to 0.47. GuidedCoding always includes that review pass, which is the main reason to
expect it to do better than plain Claude Code; it has not been shown to do better than Claude Code with one review. On 18 harder jobs (selected, not a random sample), an outside review by
another AI assistant removed further major errors when added to GuidedCoding, narrowly. Version 1.4 keeps those two
steps (the outside review for hard or consequential changes) and a test that proves the fix; it does not include a
second review pass, keeps the independent reviewer optional, and narrows a strict scope rule that probably cost errors.
GuidedCoding 1.4 as a whole has not itself been measured; it was checked in a small trial and is being evaluated in
real use. EVIDENCE.md goes through each part of /gc and what the evidence says about it.
Revision 22 replaces the earlier kit with this much shorter procedure. The earlier kit had approval screens,
evidence packets checked by its own tools, and an unattended auto mode. They are retired, and kept on the branch
full-kit-rev21.
What you gain, and what you lose:
- Gained: a shorter, prompt-only procedure that asks for your attention only when a decision is needed.
- Lost: the screens, packets, checker tools and the unattended auto mode.
/gc batchis supervised, not unattended. The earlierhelp,statusandhistorycommands have new versions (/gc help,/gc status,/gc history), and the job history is kept by default.
To move:
- Finish first. Finish or stop any job or auto queue of the earlier kit before updating.
- Your link. If your link is
~/.claude/skills/guided_codingand points tomodules/guided_coding/guided_coding, updating the repository (git pull) is enough. The link keeps working and now gives the new/gc. - A link into cctbx_project. If your link points to
cctbx_project/libtbx/guided_coding(revision 20 or older), run the move block ("Moving from the earlier kit") under "Install and register it (once)" (in bash, with$PHENIXset or from the folder that containsmodules). It clones the new GuidedCoding intomodules/guided_codingand replaces that old registration with the new one. Or type/gcwith the earlier kit: it offers to do this for you. - Two links. Keep only one link to GuidedCoding. Two skills both named
gcconflict. - Your instructions. If your
CLAUDE.local.mdadopts the earlier kit's "Developer–Guide Contract", that line can go. Your project method file is not used by the new/gc;/gc setupwrites short notes instead. - Then start a new Claude Code conversation.
To go back to the earlier kit:
cd modules/guided_coding
git fetch origin full-kit-rev21
git checkout full-kit-rev21
Your link then gives the earlier kit again. Keep your single link, and do not run the earlier kit's registration step
(register-skill), which would add a second one. Restore your CLAUDE.local.md contract line if you removed it. To
return to the new GuidedCoding, git checkout master.
python3 tst_guided_coding.py
It checks that the skill's files are present and consistent: the frontmatter, the cross-references between files (including section references into other files), and the version lines. It includes a check of its own that a broken cross-file reference is caught. It does not check whether Claude follows the procedure; that is checked by running it in Claude Code, and the recorded runs are listed in EVIDENCE.md.