This file and all skill files (
.claude/commands/*.md) must always be written in English. Exception: Korean is allowed where explicitly specified by conventions (e.g., JSDoc descriptions, component method names).
A Chrome extension that proxies Flex (flex.team) HR SaaS.
Operates without a backend — reads Flex JWT tokens directly via the browser.cookies API and calls the Flex API.
- WXT — Chrome Extension build framework
- React 19 + TypeScript 6
- Tailwind CSS v4
- Biome — linter / formatter
- Shadow DOM (Content Script CSS isolation, to be applied later)
- Single popup-based UI
- Background Service Worker kept minimal (planned for cookie change detection only)
- Flex API is called every time the popup opens (caching to be added optionally later)
entrypoints/ contains WXT boilerplate entry points. All hand-written code lives under src/.
src/
components/
atom/
molecule/
organism/
template/
api/
config/
hooks/
shadcn/
utils/
constants/
types/
Whenever the folder structure changes, always show the full tree and explicitly call out what changed.
All available slash command skills in this project. Skill files (.claude/commands/*.md) must always be written in English.
| Skill | Usage | Description |
|---|---|---|
/create-component-set |
/create-component-set <path> [description] |
Scaffolds a Component Set at the given path. Runs /validate-component-set if the path already exists. |
/validate-component-set |
/validate-component-set <path> |
Validates an existing Component Set against conventions. Reports issues before making corrections. |
/create-query-hook |
/create-query-hook [path] [--clean] |
Generates TanStack Query hook files from API files under src/api/. See options below. |
/create-query-hook options:
| Usage | Description |
|---|---|
/create-query-hook |
Scan all files under src/api/, overwrite existing hook files |
/create-query-hook --clean |
Scan all files under src/api/, delete and recreate existing hook files |
/create-query-hook src/api/auth.ts |
Process auth.ts only, overwrite existing hook file |
/create-query-hook src/api/auth.ts --clean |
Process auth.ts only, delete and recreate existing hook file |
- Claude does not edit files directly; instead issues instructions to the user with a
[TODO]prefix. - This convention may change as needed.
- Either the developer or Claude may propose updates to
CLAUDE.mdwhen deemed necessary to keep it current. - Only commit
CLAUDE.mdwhen the developer explicitly requests it using the keyword "클로드 컨텍스트". Do not commit automatically after every change. - When committing, use the message format:
docs: 📝 {description}
- All API calls must use
fetcherfromsrc/api/fetch.ts. Exceptions must be explicitly noted. - API files live under
src/api/with no exceptions. - Function naming: HTTP method as prefix +
Apias suffix (e.g.,getCustomerUserApi,postExchangeApi). - DTOs (request/response types and Zod schemas) are written in a co-located
*-dto.tsfile (e.g.,src/api/auth-dto.ts). - Every API function must accept
options?: RequestInitas the last parameter to allow request customization.
- All components follow the Atomic Design pattern.
atom/molecule/organism/templatelayers follow the standard Atomic Design definitions. Customization is allowed when needed to fit the project.- Exceptions are allowed depending on the situation.
atom/molecule— avoid depending on external state (Zustand, TanStack Query, etc.) or side effects. Keep them as pure presentational components as much as possible.organism/template— grouped by domain (page, feature, etc.).
Every component is structured as a Component Set — a dedicated folder containing:
ComponentName/
ComponentName.tsx ← component
ComponentName.spec.tsx ← tests
ComponentName.stories.tsx ← Storybook stories
index.ts ← public export
When the developer requests a component set at a specific path, the agent must scaffold this structure.
- Import
MetaandStoryObjfrom@storybook/react-vite(not@storybook/react). export default meta;must appear after all named story exports, because Biome enforces that default exports cannot precede non-exported declarations.- Story files live alongside the component as
ComponentName.stories.tsx. titlefollows the pattern{Atomic}/{Domain}/{ComponentName}(e.g.,Organism/Global/AppReactQueryProvider).{Atomic}and{Domain}match the folder names exactly.atomandmoleculelayers have no domain segment (e.g.,Atom/Button).
- Every prop must have its own dedicated story page.
- Complex states combining multiple props also get a separate story page.
- Method props are wired up using
fn()from@storybook/test. This records calls and arguments in the Actions panel, and can be extended to interaction tests later. - Story export order:
Defaultfirst,Showcasesecond, then individual prop stories in sequence. - Every component must have a
Showcasestory that displays all states at a glance. - Props that accept
ReactNodemust have their control disabled inargTypes:{ control: false }. - Add
tags: ['autodocs']to the meta object to enable the auto-generated Docs page. - Placeholder or dummy components should be styled with Tailwind CSS.
Example structure:
import type { Meta, StoryObj } from '@storybook/react-vite';
import MyComponent from './MyComponent';
const meta: Meta<typeof MyComponent> = {
component: MyComponent,
title: 'Atom/MyComponent'
};
type Story = StoryObj<typeof MyComponent>;
export const Default: Story = { args: {} };
export const Showcase: Story = { ... };
export default meta;| Skill | Usage | Description |
|---|---|---|
/create-component-set |
/create-component-set <path> [description] |
Scaffolds a Component Set at the given path. If the path already exists, runs /validate-component-set instead. |
/validate-component-set |
/validate-component-set <path> |
Validates an existing Component Set against the conventions above. Reports issues to the developer before making any corrections. |
- Hook files live under
src/hooks/react-query/, mirroring the API filename (e.g.,src/api/auth.ts→src/hooks/react-query/auth.ts). - Hook name:
use+ original API function name (e.g.,postExchangeApi→usePostExchangeApi). - Hook type is determined by the API function name:
get*InfiniteApi→useInfiniteQueryget*Api→useQuerypost*Api,put*Api,patch*Api,delete*Api→useMutation
- All original API parameters are wrapped into a
{HookName}Paramsinterface regardless of count. - Hook signature:
useQuery/useInfiniteQuery:(params: HookNameParams, options?, fetchOptions?)useMutation:(options?, fetchOptions?)— params are passed atmutate()call time.
- Query/mutation key:
useQuery/useInfiniteQuery:['domain', 'hookName', params]useMutation:['domain', 'hookName']
- Generics must always be specified explicitly.
| Skill | Usage | Description |
|---|---|---|
/create-query-hook |
/create-query-hook [path] [--clean] |
Generates TanStack Query hook files from API files under src/api/. See options below. |
/create-query-hook options:
| Usage | Description |
|---|---|
/create-query-hook |
Scan all files under src/api/, overwrite existing hook files |
/create-query-hook --clean |
Scan all files under src/api/, delete and recreate existing hook files |
/create-query-hook src/api/auth.ts |
Process auth.ts only, overwrite existing hook file |
/create-query-hook src/api/auth.ts --clean |
Process auth.ts only, delete and recreate existing hook file |
-
Testing framework is
vitest. -
Test code is written by the agent, targeting 100% coverage.
-
If 100% coverage is not achievable or requires clarification, consult with the developer before proceeding.
-
One root
describeper file. -
Root
describetitle must be prefixed with the filename:[jwt.ts] ...- Fallback title:
모듈 테스트(or컴포넌트 테스트for components). Use a more specific title if available.
- Fallback title:
-
First-level
describeblocks under root are organized by method name:[methodName] ...- Fallback title:
메서드 테스트. Use a more specific title if available.
- Fallback title:
-
Tests for each method are written freely under their respective first-level
describe. -
Further grouping with nested
describeis allowed when needed. -
Component file exception: A component file typically contains a single function. In this case, the root
describedoubles as the first-leveldescribe— no extra nesting is needed. If a component file contains more than one component, follow the standard pattern.
| Role | Cookie Name | Domain | Path | HttpOnly |
|---|---|---|---|---|
| Access Token | AID |
flex.team |
/ |
false |
| Refresh Token | V2_WS_AID |
flex.team |
/ |
false |
AIDcookie exists → user is logged inAIDmissing → attempt to reissue Access Token usingV2_WS_AID- Success → user is logged in
- Failure → user is not logged in
- Not logged in → redirect user to FlexHR login page
No token transformation — pass cookies directly in the Cookie header.