Create Custom Hook
SkillDev toolsCreate reusable React hook (useX pattern). Triggers "create hook", "new hook", "custom hook", "useAuth"/"useScroll"-style names, extracting logic from a component.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Create Custom Hook skill
What this skill tells your AI
The instructions your AI receives, as published by darkroomengineering/cc-settings in skills/hook/SKILL.md and read by ahel’s review.
Create a custom React hook following Darkroom conventions. The hook itself is stack-agnostic — what differs between satus and novus is the path alias.
Step 1 — Detect stack
Read package.json:
dependencies.next→ satus / Next.js (path alias@/, nolib/hooks/requires'use client'boundary)dependencies["react-router"]→ novus / React Router (path alias~/, components isomorphic)
Step 2 — Choose location
| Stack | Hook path |
|---|---|
| satus | lib/hooks/<name>.ts |
| novus | hooks/<name>.ts (novus puts hooks/ at the project root) |
Confirm by checking the existing lib/hooks/ or hooks/ directory structure if either pattern is unclear from package.json alone.
Step 3 — Emit template
satus / Next.js
// lib/hooks/<name>.ts
'use client'
import { useState, useEffect } from 'react'
interface Use<Name>Options {
// Hook configuration options
}
interface Use<Name>Return {
// Return type definition
}
export function use<Name>(options?: Use<Name>Options): Use<Name>Return {
// Implementation
return {
// Return values
}
}
novus / React Router
// hooks/<name>.ts
// No 'use client' — RR components are isomorphic; the hook runs wherever
// it's called from. If the hook touches browser APIs, guard with
// `typeof window !== 'undefined'` or call from inside `useEffect`.
import { useState, useEffect } from 'react'
interface Use<Name>Options {
// Hook configuration options
}
interface Use<Name>Return {
// Return type definition
}
export function use<Name>(options?: Use<Name>Options): Use<Name>Return {
// Implementation
return {
// Return values
}
}
Conventions (both stacks)
- Type everything — options interface, return interface.
- Named export —
export function useX, not default. - Prefix with
use— React hook naming convention. - No memoization — React Compiler handles it automatically.
Stack-specific
| satus | novus | |
|---|---|---|
| Directive | 'use client' (hooks live in client boundary) | None (isomorphic) |
| Browser API guard | Only runs after hydration anyway | Guard with typeof window or use useEffect |
| Path alias | @/ | ~/ |
Before you start
If this hook uses an external library, fetch docs first:
- Use Context7 MCP (
mcp__context7__resolve-library-id→get-library-docs) in Claude or when the user configured it in standalone Codex. Otherwise use official docs through native browsing or inspect the pinned local package. cc-settings does not auto-run unpinned registry MCP packages in Codex. - Run
bun info <package>to check the latest version.
Consider Using Hamo
For common use cases, prefer hamo hooks (fetch hamo docs via Context7 first):
import { useWindowSize, useRect, useIntersectionObserver } from 'hamo'
Only create custom hooks when hamo doesn't cover the use case.
Example
User: "create a useLocalStorage hook" (in satus repo)
→ Creates lib/hooks/use-local-storage.ts with 'use client' directive
User: "create a useLocalStorage hook" (in novus repo)
→ Creates hooks/use-local-storage.ts, no directive, browser-API-guarded
Arguments
$ARGUMENTS— Hook name (e.g., "useAuth", "useLocalStorage")
Signals
- GitHub stars
- 44
- Forks
- 3
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
hook- Source
- github.com/darkroomengineering/cc-settings