For the last few months I've been using AI agents in almost every part of my React Native work. At some point I noticed I was writing the same instructions over and over: how I want projects set up, what a good refactoring looks like, what to check before shipping. Every new session started from zero.
So I started turning those instructions into a harness: a set of skills and agents that encode how I actually work. It's still in alpha, I use it daily on my own projects, and here's how it's built and what I've learned so far.
My first version was just files copied into ~/.claude. Now the harness is a proper Claude Code plugin in its own git repo. Every skill and agent is called with an rnmh: prefix, so it's clear what comes from the harness and what doesn't.
The biggest change wasn't organizational, though. Once each task had its own dedicated skill, the agent's answers became noticeably more structured, and the results got better with them.
I ran the refactoring agent on my own side project, a headache tracker that's currently in alpha. The home screen had grown into a classic Long Function: one Home() component of ~330 lines with 5 useState, 5 useEffect, 3 async handlers and a three-way JSX branch, all inline.
Before:
function Home() {
const [openAttack, setOpenAttack] = useState<Attack | null>(null);
const [recent, setRecent] = useState<Attack[]>([]);
const [now, setNow] = useState(() => systemClock.now());
const [ror, setror] = useState(false);
const [reduceMotion, setReduceMotion] = useState(false);
useEffect(() => {
AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion);
const sub = AccessibilityInfo.addEventListener(
'reduceMotionChanged',
setReduceMotion,
);
return () => sub.remove();
}, []);
// ...4 more effects, 3 async handlers, ~150 lines of inline JSX
}
After:
function Home() {
const reduceMotion = useReduceMotion();
// ...same effects and handlers, unchanged
return (
<View style={styles.middle}>
{openAttack ? (
<OngoingAttackCard
openAttack={openAttack}
now={now}
pulseStyle={pulseStyle}
onSetIntensity={handleSetIntensity}
/>
) : recent.length > 0 ? (
<RecentAttacksList recent={recent} now={now} />
) : (
<Text style={styles.emptyText}>{t('home.noAttacksYet')}</Text>
)}
</View>
);
}
Every change mapped to a named refactoring from the catalog:
IntensityPicker, OngoingAttackCard, RecentAttacksList, HomeActions
useReduceMotion, plus useDictation and a generic useKeyboardVisible on the log-input screenformatTime() went to the shared formatting module, so it wouldn't be duplicated in two new components
Home() went from ~330 to ~150 lines. The total line count actually grew a bit because of new files and imports, and that's fine: the point is that each piece now has one job. Behavior didn't change, since the agent kept refactoring strictly separate from feature work, and tsc and eslint came back clean.
One honest caveat: the agent only ran static checks, not the app, so checking the screens on a simulator was still on me.
I'm planning to open the harness to other React Native developers. If you're building something similar, or would want a toolkit like this, I'd love to hear what you'd expect from it in the comments.