{"slug": "claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo", "title": "Claude Code for React Native: The CLAUDE.md, Hooks and Checks That Keep AI-Generated Expo Code Shippable", "summary": "A developer has published a setup for keeping AI-generated Expo/React Native code mergeable with Claude Code, centered on a project-level CLAUDE.md that documents the stack, commands, rules and a \"never\" list. The configuration also pre-approves safe commands and blocks risky ones in a committed .claude/settings.json, and adds hooks that type-check and lint every edit, with work broken into small planned tasks and reviewed against a mobile-specific checklist. The developer argues output quality depends less on prompting than on the project scaffolding around the agent.", "body_md": "Claude Code can write most of a React Native screen in a minute. Whether that code is shippable depends far less on the prompt than on the project around it. Give it a `CLAUDE.md` that describes your Expo stack and its rules, restrict what it's allowed to run, add hooks that type-check and lint every edit, work in small planned tasks, and review the output against a mobile-specific checklist. That setup turns \"it generated something\" into \"it generated something we can merge\".\n\nAI coding agents are very good at React Native in general and surprisingly bad at **your** React Native app in particular. They don't know you use Expo Router instead of React Navigation stacks, that native packages must be installed with `npx expo install`, that your Supabase tables need RLS, or that a web-only library will break the Android build. Left to guess, they guess like the average of the internet.\n\nThis guide is the setup we use to stop the guessing.\n\nClaude Code reads a `CLAUDE.md` file at the root of your project at the start of every session. It's the single most effective place to improve output quality, because every instruction in it applies to every task.\n\nRun `/init` inside Claude Code to generate a first draft from your codebase, then rewrite it with the things the code can't tell it. A good React Native `CLAUDE.md` covers four things: the stack, the commands, the rules and the \"never\" list.\n\n```\n# Project: Expo + Supabase mobile app\n\n## Stack\n- Expo SDK (managed workflow) with development builds, TypeScript strict mode\n- Expo Router for navigation (file-based, in app/). Do not add React Navigation stacks manually.\n- NativeWind for styling. Use className, not StyleSheet, unless animating.\n- Supabase for auth, Postgres and storage. Client lives in src/lib/supabase.ts.\n- TanStack Query for server state. No Redux.\n\n## Commands\n- Install a package: npx expo install <pkg>   (never plain npm install for native packages)\n- Type-check: npx tsc --noEmit\n- Lint: npx expo lint\n- Project health: npx expo-doctor\n- Unit tests: npm test\n\n## Rules\n- Every string rendered on screen must be inside <Text>.\n- Lists longer than ~20 items use FlatList, never .map() inside ScrollView.\n- Screens read params with useLocalSearchParams and fetch by ID; never pass whole objects as params.\n- New Supabase tables: enable RLS in the same migration and add select/insert/update/delete policies using (select auth.uid()).\n- Any new permission (camera, photos, location) needs a clear purpose string in app.json.\n- Check behavior on both iOS and Android; call out platform differences in your summary.\n\n## Never\n- Never use web-only libraries (anything that touches window, document or the DOM).\n- Never put the Supabase service role key or any secret in app code or EXPO_PUBLIC_ variables.\n- Never edit files in ios/ or android/ directly; use app.json or config plugins.\n- Never run eas build, eas submit or eas update.\n```\n\nKeep it short enough to read in a minute. Long, vague instruction files get followed less reliably than short, specific ones. When Claude Code makes the same mistake twice, that's a line missing from this file.\n\nYou can also add `CLAUDE.md` files in subfolders, such as `supabase/CLAUDE.md` with your migration conventions. They're picked up when Claude Code works in that part of the project.\n\nClaude Code asks for permission before running commands, and you can pre-approve the safe ones and block the risky ones in `.claude/settings.json`, committed to the repo so the whole team shares it:\n\n```\n{\n  \"permissions\": {\n    \"allow\": [\n      \"Bash(npx tsc --noEmit)\",\n      \"Bash(npx expo lint)\",\n      \"Bash(npx expo-doctor)\",\n      \"Bash(npx expo install:*)\",\n      \"Bash(npm test:*)\"\n    ],\n    \"deny\": [\n      \"Read(./.env)\",\n      \"Read(./.env.*)\",\n      \"Bash(eas submit:*)\",\n      \"Bash(eas update:*)\",\n      \"Bash(npx supabase db push:*)\"\n    ]\n  }\n}\n```\n\nThe allow list removes friction for checks you always want run. The deny list is about blast radius: an agent shouldn't be able to read your secrets, ship an over-the-air update to production users or push a migration to your live database. Those stay human decisions.\n\nHooks run shell commands automatically at points in Claude Code's workflow. A `PostToolUse` hook on file edits gives the agent immediate feedback, so type errors get fixed in the same turn instead of piling up:\n\n```\n{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Edit|Write\",\n        \"hooks\": [\n          { \"type\": \"command\", \"command\": \"npx tsc --noEmit --pretty false 2>&1 | head -n 30\" }\n        ]\n      }\n    ]\n  }\n}\n```\n\nOn a large project, a full type-check after every edit can be slow. In that case, run a linter or formatter on the edited file in the hook, and keep the full `tsc` and `expo-doctor` run as the final step of each task, listed in `CLAUDE.md`.\n\nThe biggest quality jump doesn't come from settings; it comes from task size. \"Build the whole onboarding flow\" produces a large diff that's hard to review and easy to get subtly wrong. Break it down:\n\n`app/`, which tables and policies are needed. Correct the plan before any code is written. This is where you catch \"I'll add React Navigation\" before it happens.\nFor tasks you repeat, save the prompt as a custom slash command in `.claude/commands/`. For example, `.claude/commands/new-screen.md`:\n\n```\nCreate a new screen for: $ARGUMENTS\n\n- Add the route file under app/ following our Expo Router structure.\n- Use NativeWind classes and our components in src/components.\n- Fetch data with TanStack Query through src/lib/api.\n- Handle loading, empty and error states.\n- Run npx tsc --noEmit and npx expo lint before finishing.\n- Summarize the files you changed.\n```\n\nNow `/new-screen order history with pull-to-refresh` produces screens that look like the rest of your app.\n\nCompiling isn't the bar. These are the problems that pass type-checking and still hurt in production. Review each diff for them:\n\n**Rendering and performance**\n\n`.map()` over long lists instead of `FlatList` (or FlashList), and missing stable `keyExtractor` s.\n**Platform behavior**\n\n`KeyboardAvoidingView`, so the keyboard covers the input.\n**Data and security**\n\n`EXPO_PUBLIC_` variables, which are bundled into the app.\n**Dependencies**\n\n`npm install` instead of `npx expo install`, which can pull versions incompatible with your SDK.\nGenerated UI often looks right in the code and wrong on a phone. Before merging any screen:\n\nClaude Code can help write those tests too; ask for them as part of the same task, not as an afterthought.\n\n`CLAUDE.md` with your stack, commands, rules and \"never\" list.`.claude/settings.json` with safe commands allowed and secrets, deploys and production migrations denied.\n**Is Claude Code good at React Native?** It's strong at TypeScript, React and common React Native patterns. Most problems come from missing project context, like which router, styling and backend you use, which is exactly what `CLAUDE.md` provides.\n\n**Can it run the app?** It can run commands like the type-checker, linter, tests and the Expo dev server, but you still need to look at the app on a device. Visual and platform-specific bugs need human eyes.\n\n**Should it write Supabase migrations?** It can draft them well, but review every policy before applying, and keep production database pushes out of its permissions.\n\n**Does this work with other AI coding tools?** The ideas do: project rules, restricted commands, automatic checks, small tasks and a review checklist. The file names and settings formats differ by tool.\n\nThe difference between AI-generated React Native code you throw away and code you ship is mostly setup: tell the agent how your app works, limit what it can touch, make it prove every edit compiles, keep tasks small, and review with mobile-specific eyes.\n\n*What's in your CLAUDE.md for React Native? Share the one rule that saved you the most time in the comments.*", "url": "https://wpnews.pro/news/claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo", "canonical_source": "https://dev.to/lucas_martin_8cb158b9a81b/claude-code-for-react-native-the-claudemd-hooks-and-checks-that-keep-ai-generated-expo-code-41mj", "published_at": "2026-11-12 12:40:21+00:00", "updated_at": "2026-11-12 12:53:02.915898+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["Claude Code", "Anthropic", "Expo", "React Native", "Supabase", "TanStack Query", "NativeWind"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo", "markdown": "https://wpnews.pro/news/claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo.md", "text": "https://wpnews.pro/news/claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo.txt", "jsonld": "https://wpnews.pro/news/claude-code-for-react-native-the-claude-md-hooks-and-checks-that-keep-ai-expo.jsonld"}}