This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Always install from the repo root with corepack — never run pnpm install per-package:
corepack pnpm installTurbo orchestrates builds across the workspace; per-task scripts live on each package and are invoked through these root scripts:
corepack pnpm build—tsupbuild for every package, respecting^builddep ordercorepack pnpm test— runsvitest run --passWithNoTestsper package; depends onbuild(so tests run against compileddist/)corepack pnpm lint/lint:fix— eslint across the workspacecorepack pnpm check-types—tsc -b --noEmitper package
To work on a single package, cd packages/<pkg> and run its scripts directly (pnpm dev for tsup --watch, pnpm test, pnpm lint, pnpm check-types). To run a single vitest file, use pnpm vitest run path/to/file.test.ts from inside the package.
Releases use Changesets in pre-release rc mode (see .changeset/pre.json). Add a changeset with corepack pnpm changeset, version with changeset:version, publish with changeset:publish.
Monorepo of independently-published @vanya2h/* libraries plus one Claude Code skill. Workspace declared in pnpm-workspace.yaml (packages/*); turbo is the task runner; node >=25 and pnpm 10.32.1 are required (enforced via engines and packageManager).
Internal workspace:* deps form this graph — keep it in mind when changing public APIs:
utils— base utilities (common,typeUtils,zod,models); the only multi-entry package (tsupemits one bundle per subpath, mirrored inexports).utils-rxjs→ depends onutils. RxJS helpers:batcher,createCache,persistBehaviorSubject(with localStorage / stub-transport persistors),wrappedstatus helpers.utils-rxjs-react→ depends onutils-rxjs. React bindings for RxJS:useObservable(concurrent-safeuseSyncExternalStore),usePending(status state machine withonReload),<Pending>,<BehaviorSubjectRender>,<OnlyIfTruthy>. Uses thereacttypescript-config andjsdomfor vitest.store→ depends onutils+utils-rxjs. Reactive global store with schema-keyed caching (createGlobalStore,createStoreDescriptor,fromFetcher).store-react→ depends onstore+utils+utils-rxjs+utils-rxjs-react. React hooks for the global store:useStoreValue(status-aware),useStoreCache(direct cache access). Pinszodto the same exact version asstore(currently4.3.6) sodtsemit doesn't see twoz.ZodTypetypes.async-actions— standalone. Composable async action pipelines (ActionSingle,ActionsSet) on top oftiny-typed-emitterandimmutable.List.utils-wagmi→ depends onutils. Wagmi/viem account + client helpers.eslint-config,prettier-config,typescript-config— shared dev-time configs.eslint-configexportsbase/node/reactsubpaths; the rooteslint.config.jsconsumes thenodeconfig.
When adding workspace deps between these, mirror the existing pattern: "@vanya2h/x": "workspace:*" in dependencies, plus @vanya2h/eslint-config and @vanya2h/typescript-config in devDependencies.
Each package follows the same shape — when scaffolding a new one, copy from packages/utils-rxjs/:
tsup.config.tsemitscjs+esm+d.tstodist/, with entries derived from a localconfig.ts(srcDir,distDir).package.jsonexportsdeclaresimport/types/default(cjs) for each entrypoint;files: ["dist", "package.json"].prepublishOnlyrunspnpm run build;cleanisrimraf ./dist.- Tests are colocated (
src/**/index.test.ts) and run viavitest run --passWithNoTestsagainst the source (vitest doesn't need the build).
Note turbo.json makes test depend on build — turbo will rebuild upstream packages before testing a downstream one. The root vitest.workspace.js is stale (points to non-existent code/ paths); per-package vitest.config.ts is what's actually used.
.changeset/config.json declares a fixed version group: eslint-config, prettier-config, typescript-config, utils, async-actions, store all bump together. utils-rxjs and utils-wagmi are versioned independently. baseBranch is main, but PRs typically target develop (see the /pr skill).
skills/integrate-configs/SKILL.md is published two ways: via npx skills add vanya2h/common -a claude-code and via the Claude plugin marketplace (/plugin marketplace add vanya2h/common). It installs the three shared configs into a target project. .claude/skills/integrate-configs is a symlink to skills/integrate-configs — edit only the canonical copy.