Earlier this year, my business mentor shared the custom GPTs he had built for his cold-outreach cohort. There were three: a cold email rewriter and scorer, a “lazy” niche picker for freelancers who can’t decide what to specialize in, and a checklist for setting up sending domains. He handed over the source material, and I set out to make them work in Claude.
The first version worked. The version I actually use took a rebuild, and most of that rebuild was deleting things. This post is what I cut, why, and the checklist I’d use for the next port.
The first port: one Project, one big pile
The obvious move was a Claude Project. I pasted each GPT’s system instructions into the project instructions and uploaded the knowledge files.
That surfaced a few practical snags right away:
- Projects wanted flat files. Folder uploads and zip uploads both failed, so 11 separate scorecard component files had to be merged into one knowledge file.
- The emoji broke. A character-encoding mismatch turned the scorecard’s 🎯 into “🎯”, and the merged file had to be re-encoded before it read cleanly.
Neither was hard to fix. The real problem showed up later.
Every tool lived in one block of instructions, and that block loaded into every chat in the project. Asking for help with a subject line still loaded the niche picker. Asking about niches still loaded the domain checklist. Each new tool made the block bigger, and every chat paid for all of it.
Why always-on context is a tax
A Claude Skill is a folder with a SKILL.md file and, optionally, a references/ folder for supporting files. The difference from project instructions is when each part loads. Anthropic’s documentation describes three levels:
- The name and description are always loaded. Claude sees them at the start of every conversation and uses the description to decide whether the skill applies.
- The
SKILL.mdbody loads only when a request matches. Until then, it costs nothing. - Reference files load only when the instructions point Claude to them.
So the question changes. With project instructions, you ask “is this useful sometimes?” and the answer is almost always yes. With a skill, you ask “does this procedure actually use this, at this step?” That second question is much harder to pass.
The audit: what came out of the niche picker
I ported the niche picker from the mentor’s fifth version of the GPT. Going file by file and asking whether the procedure used each one, three things failed:
- A 600-plus-line program overview. It described the whole coaching program. None of it was used to pick a niche.
- Example freelancer profiles. The step-by-step flow never referenced them.
- A separate menu file. The niche menu is 12 items. Twelve lines don’t need their own file, so the menu went inline.
What’s left is a single, self-contained SKILL.md.
I want to be careful about what I claim here. I didn’t run a before-and-after benchmark on the skill, so I can’t tell you the cuts made its answers measurably better. What I can tell you is what changed in practice: the tool no longer rides along in chats that have nothing to do with niches, and when it does run, everything it loads is something the procedure uses.
Write the trigger, and the non-trigger
The description is the one part of a skill that is always in context, so it does the most work. The version I kept says when to use the skill, and also when not to:
“Use this skill when a freelancer asks for help picking a niche, says they have niche paralysis… is stuck between niche options… Do NOT use for ICP / micro-niche definition, offer or service design, or lead-list building.”
Those exclusions matter because the neighboring jobs sound alike. Picking a niche and defining an ideal customer profile use many of the same words. Without the “Do NOT use for” line, a skill built for one task can take over a nearby task it was never built for.
The AI wanted to split it. I didn’t let it.
Halfway through the build, Claude proposed splitting the email writer and the email scorer into two separate skills. Then it built them that way, reversing a decision we had agreed on earlier in the same session.
I caught it and held the line. The writer and the scorer always run together, and they share one scorecard. Splitting them would mean two skills loading the same rubric and two descriptions competing for the same requests. They stayed one skill.
The domain checklist went the other way. It’s a different job, done at a different time, so it stayed separate.
The rule I took from this: group skills by how they’re used, not by what they’re called. And keep the architecture decisions with the human. The AI made the build fast. It also lost track of an earlier agreement over a long session, which is exactly the kind of drift a person has to watch for.
Shipping friction
Two more snags, for anyone doing this themselves:
- Uploading a plain
.mdfile as a skill returned “internal server error.” - A zip worked, but only when I zipped from inside the skill folder. That keeps the paths to reference files relative to the skill, so they resolve after upload.
One more thing worth knowing from the documentation: custom skills uploaded to claude.ai belong to your account on claude.ai. They don’t carry over to the Claude API or to Claude Code, which keep their own skills. Plan to install them separately on each surface you use.
Where it landed
- Three skills, installed on my account, so they follow me to my Mac, iPad and iPhone. (Four were built that day, but the split pair was merged back into one.)
- Project instructions shrank to positioning plus a short list of which skills are installed and what each one is for.
- Daily use since. In one scoring session, a sample cohort email went from a C+ (68 out of 100) to an A- (86 out of 100). That shows what the scorer does. It isn’t evidence that the cuts improved the scorer.
A porting checklist
If you have a shelf of custom GPTs and you’re moving to Claude, this is the order I’d follow:
- Inventory. List every instruction block and every knowledge file each GPT carries.
- Trace. Walk the procedure step by step and mark which files each step actually reads.
- Cut. Anything unmarked goes. Anything used by only one rare step moves to a reference file that loads on demand.
- Write the trigger and the non-trigger. Say when the skill applies, and name the neighboring tasks it must leave alone.
Porting a custom GPT isn’t copy and paste. It’s an audit.
The mobile parallel
None of this is new to anyone who has shipped a mobile app. You don’t put every feature in the launch path. You load a feature when the screen needs it, you keep the bundle lean, and you audit your dependencies before a migration, not after.
Context works the same way. The GPT versions carried everything, just in case. The skills carry only what the procedure uses. Most of context engineering, it turns out, is subtraction.
Skill loading details are from Anthropic’s Agent Skills documentation. Upload behavior on claude.ai may change.